diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index df6e4f463..18d32c4e5 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -78,7 +78,7 @@ There are several different types of declaration spaces, as described in the fol - Within all compilation units of a program, *namespace_member_declaration*s with no enclosing *namespace_declaration* are members of a single combined declaration space called the ***global declaration space***. - Within all compilation units of a program, *namespace_member_declaration*s within *namespace_declaration*s that have the same fully qualified namespace name are members of a single combined declaration space. - Each *compilation_unit* and *namespace_body* has an ***alias declaration space***. Each *extern_alias_directive* and *using_alias_directive* of the *compilation_unit* or *namespace_body* contributes a member to the alias declaration space ([§14.5.2](namespaces.md#1452-using-alias-directives)). -- Each non-partial class, struct, or interface declaration creates a new declaration space. Each partial class, struct, or interface declaration contributes to a declaration space shared by all matching parts in the same program ([§16.2.4](structs.md#1624-partial-modifier)). Names are introduced into this declaration space through *class_member_declaration*s, *struct_member_declaration*s, *interface_member_declaration*s, or *type_parameter*s. Except for overloaded instance constructor declarations and static constructor declarations, a class or struct cannot contain a member declaration with the same name as the class or struct. A class, struct, or interface permits the declaration of overloaded methods and indexers. Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)). Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Such a member is said to ***hide*** the inherited member. +- Each non-partial class, struct, or interface declaration creates a new declaration space. Each partial class, struct, or interface declaration contributes to a declaration space shared by all matching parts in the same program ([§16.2.4](structs.md#1624-partial-modifier)). Names are introduced into this declaration space through *class_member_declaration*s, *struct_member_declaration*s, *interface_member_declaration*s, or *type_parameter*s. Except for overloaded instance constructor declarations and static constructor declarations, a class, struct, or interface cannot contain a member declaration with the same name as the class, struct, or interface. A class, struct, or interface permits the declaration of overloaded methods and indexers. Furthermore, a class or struct permits the declaration of overloaded instance constructors and operators. For example, a class, struct, or interface may contain multiple method declarations with the same name, provided these method declarations differ in their signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)). Note that base classes do not contribute to the declaration space of a class, and base interfaces do not contribute to the declaration space of an interface. Thus, a derived class or interface is allowed to declare a member with the same name as an inherited member. Such a member is said to ***hide*** the inherited member. - Each delegate declaration creates a new declaration space. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_array*s) and *type_parameter*s. - Each enumeration declaration creates a new declaration space. Names are introduced into this declaration space through *enum_member_declarations*. - Each method declaration, property declaration, property accessor declaration, indexer declaration, indexer accessor declaration, operator declaration, instance constructor declaration, anonymous function, and local function creates a new declaration space called a ***local variable declaration space***. Names are introduced into this declaration space through parameters (*fixed_parameter*s and *parameter_array*s) and *type_parameter*s. The set accessor for a property or an indexer introduces the name `value` as a parameter. The body of the function member, anonymous function, or local function, if any, is considered to be nested within the local variable declaration space. When a local variable declaration space and a nested local variable declaration space contain elements with the same name, within the scope of the nested local name, the outer local name is hidden ([§7.7.1](basic-concepts.md#771-general)) by the nested local name. @@ -268,7 +268,7 @@ When access to a particular member is allowed, the member is said to be ***acces The ***declared accessibility*** of a member can be one of the following: - Public, which is selected by including a `public` modifier in the member declaration. The intuitive meaning of `public` is “access not limited”. -- Protected, which is selected by including a `protected` modifier in the member declaration. The intuitive meaning of `protected` is “access limited to the containing class or types derived from the containing class”. +- Protected, which is selected by including a `protected` modifier in the member declaration. The intuitive meaning of `protected` is “access limited to the containing class or interface, or classes or interfaces derived from the containing type”. - Internal, which is selected by including an `internal` modifier in the member declaration. The intuitive meaning of `internal` is “access limited to this assembly”. - Protected internal, which is selected by including both a `protected` and an `internal` modifier in the member declaration. The intuitive meaning of `protected internal` is “accessible within this assembly as well as types derived from the containing class”. - Private protected, which is selected by including both a `private` and a `protected` modifier in the member declaration. The intuitive meaning of `private protected` is “accessible within this assembly by the containing class and types derived from the containing class.” @@ -402,7 +402,7 @@ As described in [§7.4](basic-concepts.md#74-members), all members of a base cla ### 7.5.4 Protected access -When a `protected` or `private protected` instance member is accessed outside the program text of the class in which it is declared, and when a `protected internal` instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place *through* an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. +When a `protected` or `private protected` instance member is accessed outside the program text of the class in which it is declared, and when a `protected internal` instance member is accessed outside the program text of the program in which it is declared, the access shall take place within a class declaration that derives from the class in which it is declared. Furthermore, the access is required to take place *through* an instance of that derived class type or a class type constructed from it. This restriction prevents one derived class from accessing protected members of other derived classes, even when the members are inherited from the same base class. Instance interface members defined with `protected` or `private protected` access cannot be accessed from a `class` or `struct` that implements that interface; these can be accessed only from derived interfaces. However, `class` and `struct` types can define overridden `protected` instance members declared in an interface it implements. Let `B` be a base class that declares a protected instance member `M`, and let `D` be a class that derives from `B`. Within the *class_body* of `D`, access to `M` can take one of the following forms: @@ -781,9 +781,9 @@ When a name in an inner scope hides a name in an outer scope, it hides all overl Name hiding through inheritance occurs when classes or structs redeclare names that were inherited from base classes. This type of name hiding takes one of the following forms: -- A constant, field, property, event, or type introduced in a class or struct hides all base class members with the same name. -- A method introduced in a class or struct hides all non-method base class members with the same name, and all base class methods with the same signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)). -- An indexer introduced in a class or struct hides all base class indexers with the same signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)) . +- A constant, field, property, event, or type introduced in a class, struct, or interface hides all base class members with the same name. +- A method introduced in a class, struct, or interface hides all non-method base class members with the same name, and all base class methods with the same signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)). +- An indexer introduced in a class, struct, or interface hides all base type indexers with the same signature ([§7.6](basic-concepts.md#76-signatures-and-overloading)) . The rules governing operator declarations ([§15.10](classes.md#1510-operators)) make it impossible for a derived class to declare an operator with the same signature as an operator in a base class. Thus, operators never hide one another. @@ -913,9 +913,9 @@ where: `R₀` is determined as follows: - If `x` is zero and the *namespace_or_type_name* appears within a generic method declaration ([§15.6](classes.md#156-methods)) but outside the *attributes* of its *method-header*, and if that declaration includes a type parameter ([§15.2.3](classes.md#1523-type-parameters)) with name `I`, then `R₀` refers to that type parameter. -- Otherwise, if the *namespace_or_type_name* appears within a type declaration, then for each instance type `T` ([§15.3.2](classes.md#1532-the-instance-type)), starting with the instance type of that type declaration and continuing with the instance type of each enclosing class or struct declaration (if any): +- Otherwise, if the *namespace_or_type_name* appears within a type declaration, then for each instance type `T` ([§15.3.2](classes.md#1532-the-instance-type)), starting with the instance type of that type declaration and continuing with the instance type of each enclosing class, struct, or interface declaration (if any): - If `x` is zero and the declaration of `T` includes a type parameter with name `I`, then `R₀` refers to that type parameter. - - Otherwise, if the *namespace_or_type_name* appears within the body of the type declaration, and `T` or any of its base types contain a nested accessible type having name `I` and `x` type parameters, then `R₀` refers to that type constructed with the given type arguments. If there is more than one such type, the type declared within the more derived type is selected. + - Otherwise, if the *namespace_or_type_name* appears within the body of the type declaration, and `T` or any of its base types contain a nested accessible type having name `I` and `x` type parameters, then `R₀` refers to that type constructed with the given type arguments. If there is more than one such type, the type declared within the more derived type is selected. It is a compiler error if no type is more derived than all others. > *Note*: Non-type members (constants, fields, methods, properties, indexers, operators, instance constructors, finalizers, and static constructors) and type members with a different number of type parameters are ignored when determining the meaning of the *namespace_or_type_name*. *end note* - Otherwise, for each namespace `N`, starting with the namespace in which the *namespace_or_type_name* occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located: - If `x` is zero and `I` is the name of a namespace in `N`, then: @@ -945,7 +945,7 @@ For each repetition `n`, where `1 ≤ n ≤ k`, its resolution, `Rₙ`; which in - If `x` is zero and `Rₚ` refers to a namespace and `Rₚ` contains a nested namespace with name `I`, then `Rₙ` refers to that nested namespace. - Otherwise, if `Rₚ` refers to a namespace and `Rₚ` contains an accessible type having name `I` and `x` type parameters, then `Rₙ` refers to that type constructed with the given type arguments. -- Otherwise, if `Rₚ` refers to a (possibly constructed) class or struct type and `Rₚ` or any of its base classes contain a nested accessible type having name `I` and `x` type parameters, then `Rₙ` refers to that type constructed with the given type arguments. If there is more than one such type, the type declared within the more derived type is selected. +- Otherwise, if `Rₚ` refers to a (possibly constructed) class, struct, or interface type and `Rₚ` or any of its base types contain a nested accessible type having name `I` and `x` type parameters, then `Rₙ` refers to that type constructed with the given type arguments. If there is more than one such type, the type declared within the more derived type is selected. It is a compiler error if no type is more derived than all others. > *Note*: If the meaning of `T.I`, for some type `T`, is being determined as part of resolving the base class specification of `T` then the direct base class of `T` is considered to be `object` ([§15.2.4.2](classes.md#15242-base-classes)). *end note* - Otherwise, the *namespace_or_type_name* is invalid and a compile-time error occurs. @@ -956,6 +956,30 @@ A *namespace_or_type_name* is permitted to reference a static class ([§15.2.2.4 - The *namespace_or_type_name* is the `T` in a *namespace_or_type_name* of the form `T.I`, or - The *namespace_or_type_name* is the `T` in a *typeof_expression* ([§12.8.18](expressions.md#12818-the-typeof-operator)) of the form `typeof(T)` +> *Example*: +> +> +> ```csharp +> interface A +> { +> class NestedClass { public static void M() {} } +> } +> +> interface B +> { +> class NestedClass { public static void M() {} } +> } +> +> interface C : A, B +> { +> public void Test() { NestedClass.M(); } // ambiguity between A.NestedClass and B.NestedClass +> } +> ``` +> +> In the example above, the call to `NestedClass.M()` in `C.Test()` is ambiguous between `B.NestedClass.M()` and `A.NestedClass.M()` because neither is more derived than the other. An explicit reference to either `A.NestedClass.M()` or `B.NestedClass.M()` is required to resolve the ambiguity. +> +> *end example* + ### 7.8.2 Unqualified names Every namespace declaration and type declaration has an ***unqualified name*** determined as follows: diff --git a/standard/classes.md b/standard/classes.md index 66df09bab..ad8eef8aa 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -4,6 +4,8 @@ A class is a data structure that may contain data members (constants and fields), function members (methods, properties, events, indexers, operators, instance constructors, finalizers, and static constructors), and nested types. Class types support inheritance, a mechanism whereby a ***derived class*** can extend and specialize a ***base class***. +Structs (§16) and interfaces (§18) have members similar to classes but with certain restrictions. This clause defines the declarations for classes and class members. The clauses for structs and interfaces define the restrictions for those types in terms of the corresponding declarations in class types. + ## 15.2 Class declarations ### 15.2.1 General @@ -270,7 +272,7 @@ The base classes of a class are the direct base class and its base classes. In o Except for class `object`, every class has exactly one direct base class. The `object` class has no direct base class and is the ultimate base class of all other classes. -It is a compile-time error for a class to depend on itself. For the purpose of this rule, a class ***directly depends on*** its direct base class (if any) and *directly depends on* the nearest enclosing class within which it is nested (if any). Given this definition, the complete set of classes upon which a class depends is the transitive closure of the *directly depends on* relationship. +It is a compile-time error for a class to depend on itself. For the purpose of this rule, a class ***directly depends on*** its direct base class (if any) and *directly depends on* the type within which it is immediately nested (if any). > *Example*: The example > @@ -1096,7 +1098,7 @@ When a field, method, property, event, indexer, constructor, or finalizer declar #### 15.3.9.1 General -A type declared within a class or struct is called a ***nested type***. A type that is declared within a compilation unit or namespace is called a ***non-nested type***. +A type declared within a class, struct, or interface is called a ***nested type***. A type that is declared within a compilation unit or namespace is called a ***non-nested type***. > *Example*: In the following example: > @@ -1124,7 +1126,7 @@ The fully qualified name ([§7.8.3](basic-concepts.md#783-fully-qualified-names) #### 15.3.9.3 Declared accessibility -Non-nested types can have `public` or `internal` declared accessibility and have `internal` declared accessibility by default. Nested types can have these forms of declared accessibility too, plus one or more additional forms of declared accessibility, depending on whether the containing type is a class or struct: +Non-nested types can have `public` or `internal` declared accessibility and have `internal` declared accessibility by default. Nested types can have these forms of declared accessibility too, plus one or more additional forms of declared accessibility, depending on whether the containing type is a class, struct, or interface: - A nested type that is declared in a class can have any of the permitted kinds of declared accessibility and, like other class members, defaults to `private` declared accessibility. - A nested type that is declared in a struct can have any of three forms of declared accessibility (`public`, `internal`, or `private`) and, like other struct members, defaults to `private` declared accessibility. @@ -2049,6 +2051,8 @@ A variable initializer for an instance field cannot reference the instance being ### 15.6.1 General +[§15.6](classes.md#156-methods) and its subclauses cover method declarations in classes. That text is augmented by information about declaring methods in structs ([§16.4](structs.md#164-class-and-struct-differences)) and interfaces ([§19.4.2](interfaces.md#1942-interface-methods)). + A ***method*** is a member that implements a computation or action that can be performed by an object or class. Methods are declared using *method_declaration*s: ```ANTLR @@ -2142,6 +2146,7 @@ A declaration has a valid combination of modifiers if all of the following are t - The declaration includes at most one of the following modifiers: `static`, `virtual`, and `override`. - The declaration includes at most one of the following modifiers: `new` and `override`. - If the declaration includes the `abstract` modifier, then the declaration does not include any of the following modifiers: `static`, `virtual`, `sealed`, or `extern`. +- The declaration may include the `abstract` and `override` modifiers so that an abstract member may override a virtual member. - If the declaration includes the `private` modifier, then the declaration does not include any of the following modifiers: `virtual`, `override`, or `abstract`. - If the declaration includes the `sealed` modifier, then the declaration also includes the `override` modifier. - If the declaration includes the `partial` modifier, then it does not include any of the following modifiers: `new`, `public`, `protected`, `internal`, `private`, `virtual`, `sealed`, `override`, `abstract`, or `extern`. @@ -2913,9 +2918,9 @@ When an instance method declaration includes a `sealed` modifier, that method is When an instance method declaration includes an `abstract` modifier, that method is said to be an ***abstract method***. Although an abstract method is implicitly also a virtual method, it cannot have the modifier `virtual`. -An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. Because an abstract method provides no actual implementation, the method body of an abstract method simply consists of a semicolon. +An abstract method declaration introduces a new virtual method but does not provide an implementation of that method. Instead, non-abstract derived classes are required to provide their own implementation by overriding that method. The *method_body* of an abstract method simply consists of a semicolon. -Abstract method declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). +Abstract method declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§19.4.2](interfaces.md#1942-interface-methods)). > *Example*: In the following code > @@ -2937,7 +2942,7 @@ Abstract method declarations are only permitted in abstract classes ([§15.2.2.2 > } > ``` > -> the `Shape` class defines the abstract notion of a geometrical shape object that can paint itself. The `Paint` method is abstract because there is no meaningful default implementation. The `Ellipse` and `Box` classes are concrete `Shape` implementations. Because these classes are non-abstract, they are required to override the `Paint` method and provide an actual implementation. +> the `Shape` class defines the abstract notion of a geometrical shape object that can paint itself. The `Paint` method is abstract because there is no meaningful fallback implementation for the abstract concept of shape. The `Ellipse` and `Box` classes are concrete `Shape` implementations. Because these classes are non-abstract, they are required to override the `Paint` method and provide an actual implementation. > > *end example* @@ -3419,7 +3424,6 @@ For a ref-valued property the *ref_get_accessor_declaration* consists optional a The use of *accessor_modifier*s is governed by the following restrictions: -- An *accessor_modifier* shall not be used in an interface or in an explicit interface member implementation. - The *accessor_modifier* `readonly` is permitted only in a *property_declaration* or *indexer_declaration* that is contained directly by a *struct_declaration* ([§16.4.11](structs.md#16411-properties), [§16.4.13](structs.md#16413-indexers)). - For a property or indexer that has no `override` modifier, an *accessor_modifier* is permitted only if the property or indexer has both a get and set accessor, and then is permitted only on one of those accessors. - For a property or indexer that includes an `override` modifier, an accessor shall match the *accessor_modifier*, if any, of the accessor being overridden. @@ -3932,7 +3936,7 @@ An abstract property declaration specifies that the accessors of the property ar A property declaration that includes both the `abstract` and `override` modifiers specifies that the property is abstract and overrides a base property. The accessors of such a property are also abstract. -Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). The accessors of an inherited virtual property can be overridden in a derived class by including a property declaration that specifies an `override` directive. This is known as an ***overriding property declaration***. An overriding property declaration does not declare a new property. Instead, it simply specializes the implementations of the accessors of an existing virtual property. +Abstract property declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§19.4.3](interfaces.md#1943-interface-properties)). The accessors of an inherited virtual property can be overridden in a derived class by including a property declaration that specifies an `override` directive. This is known as an ***overriding property declaration***. An overriding property declaration does not declare a new property. Instead, it simply specializes the implementations of the accessors of an existing virtual property. The override declaration and the overridden base property are required to have the same declared accessibility. In other words, an override declaration shall not change the accessibility of the base property. However, if the overridden base property is protected internal and it is declared in a different assembly than the assembly containing the override declaration then the override declaration’s declared accessibility shall be protected. If the inherited property has only a single accessor (i.e., if the inherited property is read-only or write-only), the overriding property shall include only that accessor. If the inherited property includes both accessors (i.e., if the inherited property is read-write), the overriding property can include either a single accessor or both accessors. There shall be an identity conversion between the type of the overriding and the inherited property. @@ -4299,7 +4303,7 @@ An abstract event declaration specifies that the accessors of the event are virt An event declaration that includes both the `abstract` and `override` modifiers specifies that the event is abstract and overrides a base event. The accessors of such an event are also abstract. -Abstract event declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)). +Abstract event declarations are only permitted in abstract classes ([§15.2.2.2](classes.md#15222-abstract-classes)) and interfaces ([§19.4.4](interfaces.md#1944-interface-events)). The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an `override` modifier. This is known as an ***overriding event declaration***. An overriding event declaration does not declare a new event. Instead, it simply specializes the implementations of the accessors of an existing virtual event. diff --git a/standard/expressions.md b/standard/expressions.md index 88e5729bc..6feb2f531 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -6953,7 +6953,7 @@ A constant expression shall either have the value `null` or one of the following Only the following constructs are permitted in constant expressions: - Literals (including the `null` literal). -- References to `const` members of class and struct types. +- References to `const` members of class, struct, and interface types. - References to members of enumeration types. - References to local constants. - Parenthesized subexpressions, which are themselves constant expressions. diff --git a/standard/interfaces.md b/standard/interfaces.md index bdb9add3b..3c1328959 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -4,7 +4,10 @@ An interface defines a contract. A class or struct that implements an interface shall adhere to its contract. An interface may inherit from multiple base interfaces, and a class or struct may implement multiple interfaces. -Interfaces can contain methods, properties, events, and indexers. The interface itself does not provide implementations for the members that it declares. The interface merely specifies the members that shall be supplied by classes or structs that implement the interface. +Interfaces may contain various kinds of members, as described in [§19.4](interfaces.md#194-interface-members). The interface itself may provide an implementation for some or all of the function members that it declares. Members for which the interface does not provide an implementation are abstract. Their implementations must be supplied by classes or structs that implement the interface, or derived interface that provide an overriding definition. + + +> *Note*: Historically, adding a new function member to an interface impacted all existing consumers of that interface type; it was a breaking change. The addition of interface function member implementations allowed developers to upgrade an interface while still enabling any implementors to override that implementation. Users of the interface can accept the implementation as a non-breaking change; however, if their requirements are different, they can override the provided implementations. *end note* ## 19.2 Interface declarations @@ -127,6 +130,8 @@ A type `T` is variance-convertible to a type `T *Note*: The members in class `object` are not, strictly speaking, members of any interface ([§19.4](interfaces.md#194-interface-members)). However, the members in class `object` are available via member lookup in any interface type ([§12.5](expressions.md#125-member-lookup)). *end note* The set of members of an interface declared in multiple parts ([§15.2.7](classes.md#1527-partial-type-declarations)) is the union of the members declared in each part. The bodies of all parts of the interface declaration share the same declaration space ([§7.3](basic-concepts.md#73-declarations)), and the scope of each member ([§7.7](basic-concepts.md#77-scopes)) extends to the bodies of all the parts. -### 19.4.2 Interface methods +> *Example*: Consider an interface `IA` with an implementation for a member `M` and a property `P`. An implementing type `C` doesn't provide an implementation for either `M` or `P`. They must be accessed through a reference whose compile-time type is an interface that is implicitly convertible to `IA` or `IB`. These members aren't found through member lookup on a variable of type `C`. +> +> +> ```csharp +> interface IA +> { +> public int P { get { return 10; } } +> public void M() +> { +> Console.WriteLine("IA.M"); +> } +> } +> +> interface IB : IA +> { +> public new int P { get { return 20; } } +> void IA.M() +> { +> Console.WriteLine("IB.M"); +> } +> } +> +> class C : IB { } +> +> class Test +> { +> public static void Main() +> { +> C c = new C(); +> ((IA)c).M(); // cast needed +> Console.WriteLine($"IA.P = {((IA)c).P}"); // cast needed +> Console.WriteLine($"IB.P = {((IB)c).P}"); // cast needed +> } +> } +> ``` +> +>Within the interfaces `IA` and `IB`, member `M` is accessible directly by name. However, within method `Main`, we cannot write `c.M()` or `c.P`, as those names are not visible. To find them, casts to the appropriate interface type are needed. The declaration of `M` in `IB` uses explicit interface implementation syntax. This is necessary to make that method override the one in `IA`; the modifier `override` may not be applied to a function member. *end example* -Interface methods are declared using *interface_method_declaration*s: +### §interface-fields Interface fields -```ANTLR -interface_method_declaration - : attributes? 'new'? return_type interface_method_header - | attributes? 'new'? ref_kind ref_return_type interface_method_header - ; +This clause augments the description of fields in classes [§15.5](classes.md#155-fields) for fields declared in interfaces. -interface_method_header - : identifier '(' parameter_list? ')' ';' - | identifier type_parameter_list '(' parameter_list? ')' - type_parameter_constraints_clause* ';' - ; -``` +Interface fields are declared using *field_declaration*s ([§15.5.1](classes.md#1551-general)) with the following additional rules: + +- It is a compile-time error for *field_declaration* to declare an instance field. + +> *Example*: The following program contains static members of various kinds: +> +> +> ```csharp +> public interface IX +> { +> public const int Constant = 100; +> protected static int field; +> +> static IX() +> { +> Console.WriteLine("static members initialized"); +> Console.WriteLine($"constant = {IX.Constant}, field = {IX.field}"); +> field = 50; +> Console.WriteLine("static constructor has run"); +> } +> } +> +> public class Test: IX +> { +> public static void Main() +> { +> Console.WriteLine($"constant = {IX.Constant}, field = {IX.field}"); +> } +> } +> ``` +> +> The output produced is +> +> ```console +> static members initialized +> constant = 100, field = 0 +> static constructor has run +> constant = 100, field = 50 +> ``` +> +> *end example* + +See §interface-static-constructors for information regarding the allocation and initialization of static fields. -The *attributes*, *return_type*, *ref_return_type*, *identifier*, and *parameter_list* of an interface method declaration have the same meaning as those of a method declaration in a class ([§15.6](classes.md#156-methods)). An interface method declaration is not permitted to specify a method body, and the declaration therefore always ends with a semicolon. +### 19.4.2 Interface methods + +This clause augments the description of methods in classes [§15.6](classes.md#156-methods) for methods declared in interfaces. -All parameter types of an interface method shall be input-safe ([§19.2.3.2](interfaces.md#19232-variance-safety)), and the return type shall be either `void` or output-safe. In addition, any output or reference parameter types shall also be output-safe. +Interface methods are declared using *method_declaration*s (§15.6)). The *attributes*, *return_type*, *ref_return_type*, *identifier*, and *parameter_list* of an interface method declaration have the same meaning as those of a method declaration in a class. Interface methods have the following additional rules: -> *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note* +- *method_modifier* shall not include `override`. +- A method whose body is a semi-colon (`;`) is `abstract`; the `abstract` modifier is not required, but is allowed. +- An interface method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. +- A *method_declaration* shall not have *type_parameter_constraints_clause*s unless it also has a *type_parameter_list*. +- The list of requirements for valid combinations of modifiers stated for a class method is extended, as follows: + - A static declaration that is not extern shall have a block body or expression body as a *method_body*. + - A virtual declaration that is not extern shall have a block body or expression body as a *method_body*. + - A private declaration that is not extern shall have a block body or expression body as a *method_body*. + - A sealed declaration that is not extern shall have a block body or expression body as a *method_body*. + - An async declaration shall have a block body or expression body as a *method_body*. +- All parameter types of an interface method shall be input-safe ([§19.2.3.2](interfaces.md#19232-variance-safety)), and the return type shall be either `void` or output-safe. +- Any output or reference parameter types shall also be output-safe. -Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameters of the method shall be input-safe. + > *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note* -Furthermore, each class type constraint, interface type constraint and type parameter constraint on any type parameter of the method shall be input-safe. +- Each class type constraint, interface type constraint and type parameter constraint on any type parameters of the method shall be input-safe. These rules ensure that any covariant or contravariant usage of the interface remains typesafe. @@ -286,14 +381,17 @@ These rules ensure that any covariant or contravariant usage of the interface re > Were this restriction not in place it would be possible to violate type safety in the following manner: > > -> > ```csharp +> interface I +> { +> void M() where U : T; +> } > class B {} > class D : B {} > class E : B {} > class C : I > { -> public void M() {...} +> public void M() {...} > } > > ... @@ -305,75 +403,164 @@ These rules ensure that any covariant or contravariant usage of the interface re > This is actually a call to `C.M`. But that call requires that `E` derive from `D`, so type safety would be violated here. > > *end example* + -### 19.4.3 Interface properties + +> *Note*: See §interface-fields for an example that not only shows a static method with an implementation, but as that method is called `Main` and has the right return type and signature, it’s also an entry point. *end note* -Interface properties are declared using *interface_property_declaration*s: +A virtual method with implementation declared in an interface may be overridden to be abstract in a derived interface. This is known as ***reabstraction***. -```ANTLR -interface_property_declaration - : attributes? 'new'? type identifier '{' interface_accessors '}' - | attributes? 'new'? ref_kind type identifier '{' ref_interface_accessor '}' - ; +> *Example*: +> +> +> ```csharp +> interface IA +> { +> void M() { Console.WriteLine("IA.M"); } +> } +> +> interface IB: IA +> { +> abstract void IA.M(); // reabstraction of M +> } +> ``` +> +> This is useful in derived interfaces where the implementation of a method is inappropriate and a more appropriate implementation should be provided by implementing classes. *end example* -interface_accessors - : attributes? 'get' ';' - | attributes? 'set' ';' - | attributes? 'get' ';' attributes? 'set' ';' - | attributes? 'set' ';' attributes? 'get' ';' - ; +### 19.4.3 Interface properties -ref_interface_accessor - : attributes? 'get' ';' - ; -``` +This clause augments the description of properties in classes [§15.7](classes.md#157-properties) for properties declared in interfaces. -The *attributes*, *type*, and *identifier* of an interface property declaration have the same meaning as those of a property declaration in a class ([§15.7](classes.md#157-properties)). +Interface properties are declared using *property_declaration*s ([§15.7.1](classes.md#1571-general)) with the following additional rules: -The accessors of an interface property declaration correspond to the accessors of a class property declaration ([§15.7.3](classes.md#1573-accessors)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the property is read-write, read-only, or write-only. +- *property_modifier* shall not include `override`. +- An explicit interface member implementation shall not contain an *accessor_modifier* (§15.7.3). +- A derived interface may explicitly implement an abstract interface property declared in a base interface. -The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. + > *Note*: As an interface cannot contain instance fields, an interface property cannot be an instance auto-property, as that would require the declaration of implicit hidden instance fields. *end note* -### 19.4.4 Interface events +- The type of an interface property shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. +- An interface method declaration that has a block body or expression body as a *method_body* is `virtual`; the `virtual` modifier is not required, but is allowed. +- An instance *property_declaration* that has no implementation is `abstract`; the `abstract` modifier is not required, but is allowed. It is *never* considered to be an automatically implemented property ([§15.7.4](classes.md#1574-automatically-implemented-properties)). -Interface events are declared using *interface_event_declaration*s: +### 19.4.4 Interface events -```ANTLR -interface_event_declaration - : attributes? 'new'? 'event' type identifier ';' - ; -``` +This clause augments the description of events in classes [§15.8](classes.md#158-events) for events declared in interfaces. -The *attributes*, *type*, and *identifier* of an interface event declaration have the same meaning as those of an event declaration in a class ([§15.8](classes.md#158-events)). +Interface events are declared using *event_declaration*s ([§15.8.1](classes.md#1581-general)), with the following additional rules: -The type of an interface event shall be input-safe. +- *event_modifier* shall not include `override`. +- A derived interface may implement an abstract interface event declared in a base interface (§15.8.5). +- It is a compile-time error for *variable_declarators* in an instance *event_declaration* to contain any *variable_initializer*s. +- An instance event with the `virtual` or `sealed` modifiers must declare accessors. It is *never* considered to be an automatically implemented field-like event ([§15.8.2](classes.md#1582-field-like-events)). +- An instance event with the `abstract` modifier must not declare accessors. +- The type of an interface event shall be input-safe. ### 19.4.5 Interface indexers -Interface indexers are declared using *interface_indexer_declaration*s: +This clause augments the description of indexers in classes [§15.9](classes.md#159-indexers) for indexers declared in interfaces. -```ANTLR -interface_indexer_declaration - : attributes? 'new'? type 'this' '[' parameter_list ']' - '{' interface_accessors '}' - | attributes? 'new'? ref_kind type 'this' '[' parameter_list ']' - '{' ref_interface_accessor '}' - ; -``` +Interface indexers are declared using *indexer_declaration*s ([§15.9](classes.md#159-indexers)), with the following additional rules: -The *attributes*, *type*, and *parameter_list* of an interface indexer declaration have the same meaning as those of an indexer declaration in a class ([§15.9](classes.md#159-indexers)). +- *indexer_modifier* shall not include `override`. +- An *indexer_declaration* that has an *expression body* or contains an accessor with a block body or expression body is `virtual`; the `virtual` modifier is not required, but is allowed. +- An *indexer_declaration* whose accessor bodies are semi-colons (`;`) is `abstract`; the `abstract` modifier is not required, but is allowed. +- All the parameter types of an interface indexer shall be input-safe ([§19.2.3.2](interfaces.md#19232-variance-safety)). +- Any output or reference parameter types shall also be output-safe. -The accessors of an interface indexer declaration correspond to the accessors of a class indexer declaration ([§15.9](classes.md#159-indexers)), except that the *accessor_body* shall always be a semicolon. Thus, the accessors simply indicate whether the indexer is read-write, read-only, or write-only. + > *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note* -All the parameter types of an interface indexer shall be input-safe ([§19.2.3.2](interfaces.md#19232-variance-safety)). In addition, any output or reference parameter types shall also be output-safe. +- The type of an interface indexer shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. -> *Note*: Output parameters are required to be input-safe due to common implementation restrictions. *end note* +### §interface-operators Interface operators -The type of an interface indexer shall be output-safe if there is a get accessor, and shall be input-safe if there is a set accessor. +This clause augments the description of *operator_declaration* members in classes [§15.10](classes.md#1510-operators) for operators declared in interfaces. + +An *operator_declaration* in an interface is the implementation ([§19.1](interfaces.md#191-general)). + +It is a compile-time error for an interface to declare a conversion, equality, or inequality operator. + +### §interface-static-constructors Interface static constructors + +This clause augments the description of static constructors in classes [§15.12](classes.md#1512-static-constructors) for static constructors declared in interfaces. + +The static constructor for a closed (§8.4.3) interface executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following actions to occur within an application domain: + +- Any of the static members of the interface are referenced. +- Before the `Main` method is called for an interface containing the `Main` method ([§7.1](basic-concepts.md#71-application-startup)) in which execution begins. +- That interface provides an implementation for a member, and that implementation is accessed as the most specific implementation (§most-specific-implementation) for that member. + +> *Note*: In the case where none of the preceding actions take place, the static constructor for an interface may not execute for a program where instances of types that implement the interface are created and used. *end note* + +To initialize a new closed interface type, first a new set of static fields for that particular closed type is created. Each of the static fields is initialized to its default value. Next, the static field initializers are executed for those static fields. Finally, the static constructor is executed. + +> *Note*: See §interface-fields for an example of using various kinds of static members (including a Main method) declared within an interface. *end note* + +### §interface-nested-types Interface nested types + +This clause augments the description of nested types in classes [§15.3.9](classes.md#1539-nested-types) for nested types declared in interfaces. + +It is an error to declare a class type, struct type, or enum type within the scope of a type parameter that was declared with a *variance_annotation* ([§19.2.3.1](interfaces.md#19231-general)). + +> *Example*: The declaration of `C` below is an error. +> +> +> ```csharp +> interface IOuter +> { +> class C { } // error: class declaration within scope of variant type parameter 'T' +> } +> ``` +> +> *end example* + +### §most-specific-implementation most specific implementation + +Every class and struct shall have a most specific implementation for every virtual member declared in all interfaces implemented by that type among the implementations appearing in the type or its direct and indirect interfaces. The ***most specific implementation*** is a unique implementation that is more specific than every other implementation. + +> *Note*: The most specific implementation rule ensures that an ambiguity arising from diamond interface inheritance is resolved explicitly by the programmer at the point where the conflict occurs. *end note* + +For a type `T` that is a struct or a class that implements interfaces `I2` and `I3`, where `I2` and `I3` both derive directly or indirectly from interface `I` that declares a member `M`, the most specific implementation of `M` is: + +- If `T` declares an implementation of `I.M`, that implementation is the most specific implementation. +- Otherwise, if `T` is a class and a direct or indirect base class declares an implementation of `I.M`, the most derived base class of `T` is the most specific implementation. +- Otherwise, if `I2` and `I3` are interfaces implemented by `T` and `I3` derives from `I2` either directly or indirectly, `I3.M` is a more specific implementation than `I2.M`. +- Otherwise, neither `I2.M` nor `I3.M` are more specific and an error occurs. + +> *Example*: +> +> +> ```csharp +> interface IA +> { +> void M() { Console.WriteLine("IA.M"); } +> } +> +> interface IB : IA +> { +> void IA.M() { Console.WriteLine("IB.M"); } +> } +> +> interface IC: IA +> { +> void IA.M() { Console.WriteLine("IC.M"); } +> } +> +> abstract class C: IB, IC { } // error: no most specific implementation for 'IA.M' +> +> abstract class D: IA, IB, IC // OK +> { +> public abstract void M(); +> } +> ``` +> +> The most specific implementation rule ensures that a conflict (i.e., an ambiguity arising from diamond inheritance) is resolved explicitly by the programmer at the point where the conflict arises. *end example* ### 19.4.6 Interface member access -Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a method, property, or event of that interface type, and `A` is an indexer argument list. +Interface members are accessed through member access ([§12.8.7](expressions.md#1287-member-access)) and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) expressions of the form `I.M` and `I[A]`, where `I` is an interface type, `M` is a constant, field, method, property, or event of that interface type, and `A` is an indexer argument list. + +In a class `D`, with direct or indirect base class `B`, where `B` directly or indirectly implements interface `I` and `I` defines a method `M()`, the expression `base.M()` is valid only if `base.M()` staticly (§12.3) binds to an implementation of `M()` in a class type. For interfaces that are strictly single-inheritance (each interface in the inheritance chain has exactly zero or one direct base interface), the effects of the member lookup ([§12.5](expressions.md#125-member-lookup)), method invocation ([§12.8.10.2](expressions.md#128102-method-invocations)), and indexer access ([§12.8.12.4](expressions.md#128124-indexer-access)) rules are exactly the same as for classes and structs: More derived members hide less derived members with the same name or signature. However, for multiple-inheritance interfaces, ambiguities can occur when two or more unrelated base interfaces declare members with the same name or signature. This subclause shows several examples, some of which lead to ambiguities and others which don’t. In all cases, explicit casts can be used to resolve the ambiguities. @@ -531,6 +718,10 @@ When an interface is part of a namespace, a qualified interface member name can Interfaces may be implemented by classes and structs. To indicate that a class or struct directly implements an interface, the interface is included in the base class list of the class or struct. +A class or struct `C` that implements an interface `I` must provide or inherit an implementation for every member declared in `I` that `C` can access. Public members of `I` may be defined in public members of `C`. Non-public members declared in `I` that are accessible in `C` may be defined in `C` using explicit interface implementation (§19.6.2). + + A member in a derived type that satisfies interface mapping (§19.6.5) but does not implement the matching base interface member introduces a new member. This occurs when explicit interface implementation is required to define the interface member. + > *Example*: > > @@ -601,7 +792,10 @@ The base interfaces of a generic class declaration shall satisfy the uniqueness ### 19.6.2 Explicit interface member implementations -For purposes of implementing interfaces, a class or struct may declare ***explicit interface member implementations***. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. + +For purposes of implementing interfaces, a class, struct, or interface may declare ***explicit interface member implementations***. An explicit interface member implementation is a method, property, event, or indexer declaration that references a qualified interface member name. A class or struct that implements a non-public member in a base interface must declare an explicit interface member implementation. An interface that implements a member in a base interface must declare an explicit interface member implementation. + +A derived interface member that satisfies interface mapping (§19.6.5) hides the base interface member (§7.7.2). The compiler shall issue a warning unless the `new` modifier is present. > *Example*: > @@ -655,7 +849,7 @@ For purposes of implementing interfaces, a class or struct may declare ***explic > > *end example* -It is not possible to access an explicit interface member implementation through its qualified interface member name in a method invocation, property access, event access, or indexer access. An explicit interface member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name. +It is not possible to access an explicit interface member implementation through its qualified interface member name in a method invocation, property access, event access, or indexer access. An explicit interface instance member implementation can only be accessed through an interface instance, and is in that case referenced simply by its member name. An explicit interface static member implementation can only be accessed through the interface name. It is a compile-time error for an explicit interface member implementation to include any modifiers ([§15.6](classes.md#156-methods)) other than `extern` or `async`. @@ -692,11 +886,11 @@ A *type_parameter_constraints_clause* on an explicit interface method implementa > Explicit interface member implementations serve two primary purposes: > > - Because explicit interface member implementations are not accessible through class or struct instances, they allow interface implementations to be excluded from the public interface of a class or struct. This is particularly useful when a class or struct implements an internal interface that is of no interest to a consumer of that class or struct. -> - Explicit interface member implementations allow disambiguation of interface members with the same signature. Without explicit interface member implementations it would be impossible for a class or struct to have different implementations of interface members with the same signature and return type, as would it be impossible for a class or struct to have any implementation at all of interface members with the same signature but with different return types. +> - Explicit interface member implementations allow disambiguation of interface members with the same signature. Without explicit interface member implementations it would be impossible for a class, struct, or interface to have different implementations of interface members with the same signature and return type, as would it be impossible for a class, struct, or interface to have any implementation at all of interface members with the same signature but with different return types. > > *end note* -For an explicit interface member implementation to be valid, the class or struct shall name an interface in its base class list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter array, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter array then an associated explicit interface member implementation shall not have a parameter array. +For an explicit interface member implementation to be valid, the class, struct, or interface shall name an interface in its base class or base interface list that contains a member whose qualified interface member name, type, number of type parameters, and parameter types exactly match those of the explicit interface member implementation. If an interface function member has a parameter array, the corresponding parameter of an associated explicit interface member implementation is allowed, but not required, to have the `params` modifier. If the interface function member does not have a parameter array then an associated explicit interface member implementation shall not have a parameter array. > *Example*: Thus, in the following class > @@ -872,9 +1066,9 @@ When a generic method implicitly implements an interface method, the constraints ### 19.6.5 Interface mapping -A class or struct shall provide implementations of all members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as ***interface mapping***. +A class or struct shall provide implementations of all abstract members of the interfaces that are listed in the base class list of the class or struct. The process of locating implementations of interface members in an implementing class or struct is known as ***interface mapping***. -Interface mapping for a class or struct `C` locates an implementation for each member of each interface specified in the base class list of `C`. The implementation of a particular interface member `I.M`, where `I` is the interface in which the member `M` is declared, is determined by examining each class or struct `S`, starting with `C` and repeating for each successive base class of `C`, until a match is located: +Interface mapping for a class or struct `C` locates an implementation for each member of each interface specified in the base class list of `C`. The implementation of a particular interface member `I.M`, where `I` is the interface in which the member `M` is declared, is determined by examining each class, interface, or struct `S`, starting with `C` and repeating for each successive base class and implemented interface of `C`, until a match is located: - If `S` contains a declaration of an explicit interface member implementation that matches `I` and `M`, then this member is the implementation of `I.M`. - Otherwise, if `S` contains a declaration of a non-static public member that matches `M`, then this member is the implementation of `I.M`. If more than one member matches, it is unspecified which member is the implementation of `I.M`. This situation can only occur if `S` is a constructed type where the two members as declared in the generic type have different signatures, but the type arguments make their signatures identical. @@ -903,7 +1097,7 @@ Members of a constructed interface type are considered to have any type paramete > > *end example* -For purposes of interface mapping, a class or struct member `A` matches an interface member `B` when: +For purposes of interface mapping, a class, interface, or struct member `A` matches an interface member `B` when: - `A` and `B` are methods, and the name, type, and parameter lists of `A` and `B` are identical. - `A` and `B` are properties, the name and type of `A` and `B` are identical, and `A` has the same accessors as `B` (`A` is permitted to have additional accessors if it is not an explicit interface member implementation). @@ -1269,7 +1463,7 @@ When a class implements an interface, it implicitly also implements all that int ### 19.6.8 Abstract classes and interfaces -Like a non-abstract class, an abstract class shall provide implementations of all members of the interfaces that are listed in the base class list of the class. However, an abstract class is permitted to map interface methods onto abstract methods. +Like a non-abstract class, an abstract class shall provide implementations of all abstract members of the interfaces that are listed in the base class list of the class. However, an abstract class is permitted to map interface methods onto abstract methods. > *Example*: > diff --git a/standard/namespaces.md b/standard/namespaces.md index 7abbb06db..286bdf53d 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -770,7 +770,7 @@ A *type_declaration* can occur as a top-level declaration in a compilation unit When a type declaration for a type `T` occurs as a top-level declaration in a compilation unit, the fully qualified name ([§7.8.3](basic-concepts.md#783-fully-qualified-names)) of the type declaration is the same as the unqualified name of the declaration ([§7.8.2](basic-concepts.md#782-unqualified-names)). When a type declaration for a type `T` occurs within a namespace, class, or struct declaration, the fully qualified name ([§7.8.3](basic-concepts.md#783-fully-qualified-names)) of the type declaration is `S.N`, where `S` is the fully qualified name of the containing namespace, class, or struct declaration, and `N` is the unqualified name of the declaration. -A type declared within a class or struct is called a nested type ([§15.3.9](classes.md#1539-nested-types)). +A type declared within a class, interface, or struct is called a nested type ([§15.3.9](classes.md#1539-nested-types)). The permitted access modifiers and the default access for a type declaration depend on the context in which the declaration takes place ([§7.5.2](basic-concepts.md#752-declared-accessibility)): diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.gruntree.red.txt b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.gruntree.red.txt index 53e3487ad..fe5647038 100644 --- a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.gruntree.red.txt +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.gruntree.red.txt @@ -730,16 +730,20 @@ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_member_declaration ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_method_declaration +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ method_declaration +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ method_modifiers ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ return_type ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ void ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_method_header +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ method_header ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ identifier -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ A +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ member_name +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ identifier +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ A +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ( ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ @@ -763,6 +767,9 @@ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ) +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ method_body ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ; ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ @@ -770,7 +777,7 @@ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_member_declaration ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_property_declaration +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ property_declaration ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ type ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ @@ -779,18 +786,36 @@ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ identifier -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ Value +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ member_name +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ identifier +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ Value +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ { ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ interface_accessors -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ get -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ; -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ set -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ; +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ property_body +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ { +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ accessor_declarations +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ get_accessor_declaration +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ get +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ accessor_body +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ; +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ set_accessor_declaration +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ set +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎛ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ accessor_body +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ; +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ +⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ } ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ -⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ } ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎝ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ ⎜ } diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.stderr.txt b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.red.txt b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.red.txt index c3566db3d..18c40e873 100644 --- a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.red.txt +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.red.txt @@ -1 +1 @@ -(prog (compilation_unit (namespace_declaration namespace (qualified_identifier (identifier My)) (namespace_body { (namespace_member_declaration (struct_declaration (struct_modifier public) struct (identifier S) (struct_interfaces : (interface_type_list (identifier I))) (struct_body { (struct_member_declaration (constructor_declaration (constructor_modifier public) (constructor_declarator (identifier S) ( )) (constructor_body (block { })))) (struct_member_declaration (field_declaration (field_modifier private) (type (integral_type int)) (variable_declarators (identifier f1)) ;)) (struct_member_declaration (field_declaration (attributes (attribute_section [ (attribute_list (attribute (attribute_name (identifier Obsolete)) (attribute_arguments ( (positional_argument_list (positional_argument (literal "Use Script instead")) , (positional_argument (argument_name (identifier error) :) (attribute_argument_expression (boolean_literal false)))) )))) ])) (field_modifier private) (field_modifier volatile) (type (integral_type int)) (variable_declarators (identifier f2)) ;)) (struct_member_declaration (method_declaration (method_modifiers (method_modifier (ref_method_modifier public)) (method_modifier (ref_method_modifier abstract))) (return_type (integral_type int)) (method_header (member_name (identifier m)) (type_parameter_list < (decorated_type_parameter (identifier T)) >) ( (parameter_list (fixed_parameter (type (identifier T)) (identifier t))) ) (type_parameter_constraints_clause where (type_parameter (identifier T)) : (type_parameter_constraints (primary_constraint struct)))) (method_body (block { (statement_list (return_statement return (expression (literal 1)) ;)) })))) (struct_member_declaration (property_declaration (property_modifier public) (type (class_type string)) (member_name (identifier P)) (property_body { (accessor_declarations (get_accessor_declaration get (accessor_body (block { (statement_list (statement (declaration_statement (local_variable_declaration (explicitly_typed_local_variable_declaration (type (integral_type int)) (explicitly_typed_local_variable_declarators (explicitly_typed_local_variable_declarator (identifier (contextual_keyword value)) = (local_variable_initializer (literal 0)))))) ;)) (statement (return_statement return (expression (literal "A")) ;))) }))) (set_accessor_declaration set (accessor_body ;))) }))) (struct_member_declaration (property_declaration (property_modifier public) (property_modifier abstract) (type (class_type string)) (member_name (identifier P)) (property_body { (accessor_declarations (get_accessor_declaration get (accessor_body ;))) }))) (struct_member_declaration (indexer_declaration (indexer_modifier public) (indexer_modifier abstract) (indexer_declarator (type (integral_type int)) this [ (parameter_list (fixed_parameter (type (integral_type int)) (identifier index))) ]) (indexer_body { (accessor_declarations (get_accessor_declaration get (accessor_body ;)) (set_accessor_declaration (accessor_modifier internal protected) set (accessor_body ;))) }))) (struct_member_declaration (event_declaration (event_modifier public) event (type (identifier Event)) (variable_declarators (identifier E)) ;)) (struct_member_declaration (operator_declaration (operator_modifier public) (operator_modifier static) (operator_declarator (binary_operator_declarator (type (identifier A)) operator (overloadable_binary_operator +) ( (fixed_parameter (type (identifier A)) (identifier first)) , (fixed_parameter (type (identifier A)) (identifier second)) ))) (operator_body (block { (statement_list (return_statement return (expression (invocation_expression (primary_expression (member_access (primary_expression (identifier first)) . (identifier Add))) ( (argument_list (identifier second)) ))) ;)) })))) (struct_member_declaration (fixed_size_buffer_declaration fixed (buffer_element_type (integral_type int)) (fixed_size_buffer_declarators (fixed_size_buffer_declarator (identifier field) [ (constant_expression (literal 10)) ])) ;)) (struct_member_declaration (class_declaration class (identifier C) (class_body { }))) }))) (namespace_member_declaration (interface_declaration (interface_modifier public) interface (identifier I) (interface_body { (interface_member_declaration (interface_method_declaration (return_type void) (interface_method_header (identifier A) ( (parameter_list (fixed_parameter (type (integral_type int)) (identifier (contextual_keyword value)))) ) ;))) (interface_member_declaration (interface_property_declaration (type (class_type string)) (identifier Value) { (interface_accessors get ; set ;) })) }))) })))) +(prog (compilation_unit (namespace_declaration namespace (qualified_identifier (identifier My)) (namespace_body { (namespace_member_declaration (struct_declaration (struct_modifier public) struct (identifier S) (struct_interfaces : (interface_type_list (identifier I))) (struct_body { (struct_member_declaration (constructor_declaration (constructor_modifier public) (constructor_declarator (identifier S) ( )) (constructor_body (block { })))) (struct_member_declaration (field_declaration (field_modifier private) (type (integral_type int)) (variable_declarators (identifier f1)) ;)) (struct_member_declaration (field_declaration (attributes (attribute_section [ (attribute_list (attribute (attribute_name (identifier Obsolete)) (attribute_arguments ( (positional_argument_list (positional_argument (literal "Use Script instead")) , (positional_argument (argument_name (identifier error) :) (attribute_argument_expression (boolean_literal false)))) )))) ])) (field_modifier private) (field_modifier volatile) (type (integral_type int)) (variable_declarators (identifier f2)) ;)) (struct_member_declaration (method_declaration (method_modifiers (method_modifier (ref_method_modifier public)) (method_modifier (ref_method_modifier abstract))) (return_type (integral_type int)) (method_header (member_name (identifier m)) (type_parameter_list < (decorated_type_parameter (identifier T)) >) ( (parameter_list (fixed_parameter (type (identifier T)) (identifier t))) ) (type_parameter_constraints_clause where (type_parameter (identifier T)) : (type_parameter_constraints (primary_constraint struct)))) (method_body (block { (statement_list (return_statement return (expression (literal 1)) ;)) })))) (struct_member_declaration (property_declaration (property_modifier public) (type (class_type string)) (member_name (identifier P)) (property_body { (accessor_declarations (get_accessor_declaration get (accessor_body (block { (statement_list (statement (declaration_statement (local_variable_declaration (explicitly_typed_local_variable_declaration (type (integral_type int)) (explicitly_typed_local_variable_declarators (explicitly_typed_local_variable_declarator (identifier (contextual_keyword value)) = (local_variable_initializer (literal 0)))))) ;)) (statement (return_statement return (expression (literal "A")) ;))) }))) (set_accessor_declaration set (accessor_body ;))) }))) (struct_member_declaration (property_declaration (property_modifier public) (property_modifier abstract) (type (class_type string)) (member_name (identifier P)) (property_body { (accessor_declarations (get_accessor_declaration get (accessor_body ;))) }))) (struct_member_declaration (indexer_declaration (indexer_modifier public) (indexer_modifier abstract) (indexer_declarator (type (integral_type int)) this [ (parameter_list (fixed_parameter (type (integral_type int)) (identifier index))) ]) (indexer_body { (accessor_declarations (get_accessor_declaration get (accessor_body ;)) (set_accessor_declaration (accessor_modifier internal protected) set (accessor_body ;))) }))) (struct_member_declaration (event_declaration (event_modifier public) event (type (identifier Event)) (variable_declarators (identifier E)) ;)) (struct_member_declaration (operator_declaration (operator_modifier public) (operator_modifier static) (operator_declarator (binary_operator_declarator (type (identifier A)) operator (overloadable_binary_operator +) ( (fixed_parameter (type (identifier A)) (identifier first)) , (fixed_parameter (type (identifier A)) (identifier second)) ))) (operator_body (block { (statement_list (return_statement return (expression (invocation_expression (primary_expression (member_access (primary_expression (identifier first)) . (identifier Add))) ( (argument_list (identifier second)) ))) ;)) })))) (struct_member_declaration (fixed_size_buffer_declaration fixed (buffer_element_type (integral_type int)) (fixed_size_buffer_declarators (fixed_size_buffer_declarator (identifier field) [ (constant_expression (literal 10)) ])) ;)) (struct_member_declaration (class_declaration class (identifier C) (class_body { }))) }))) (namespace_member_declaration (interface_declaration (interface_modifier public) interface (identifier I) (interface_body { (interface_member_declaration (method_declaration method_modifiers (return_type void) (method_header (member_name (identifier A)) ( (parameter_list (fixed_parameter (type (integral_type int)) (identifier (contextual_keyword value)))) )) (method_body ;))) (interface_member_declaration (property_declaration (type (class_type string)) (member_name (identifier Value)) (property_body { (accessor_declarations (get_accessor_declaration get (accessor_body ;)) (set_accessor_declaration set (accessor_body ;))) }))) }))) })))) diff --git a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.svg b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.svg index ca86b258d..70703ce21 100644 --- a/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.svg +++ b/tools/GrammarTesting/Tests/Parsing/Samples/v6/AllInOneNoPreprocessor-v6-split/part-H/Reference/sample.tree.svg @@ -1,12 +1,12 @@ - - - - + + + + - - - + + + @@ -326,1535 +326,1580 @@ - - - + + + - - + + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -variable_declarators - - - -abstract - - - -literal - - - -local_variable_declaration - - - -event_modifier - - - -type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +accessor_body - - -this + + +m - - -property_declaration + + +set_accessor_declaration - - -field_modifier + + +statement - - -set_accessor_declaration + + +integral_type - - -: + + +identifier - - -; + + +accessor_body - - -) + + +. - - -indexer_declaration + + +identifier - - -literal + + +integral_type - - -set + + +variable_declarators - - -Obsolete + + +fixed_parameter - - -string + + +interface_member_declaration - - -identifier + + +Value - - -event + + +fixed_size_buffer_declarators - - -type + + +method_modifier - - -public + + +statement_list - - + + struct_member_declaration - - -{ + + +constructor_body - - -where + + +} - - -identifier + + +accessor_declarations - - -S + + +property_modifier - - + + identifier - - -get - - - -struct + + +operator_declaration - - -type + + +block - - -1 + + +; - - + + { - - -{ + + +public - - + + type - - -} + + +f1 - - -{ + + +, - - -statement + + +member_name - - -integral_type + + +property_modifier - - -public + + +variable_declarators - - -[ + + +field_modifier - - -int + + +literal - - -operator_body + + +private - - -int + + +{ - - -operator_modifier + + +positional_argument - - -] + + +argument_name - - -method_modifiers + + +int - - -invocation_expression + + +method_modifiers - - -struct_member_declaration + + +accessor_body - - -literal + + +fixed_parameter - - -integral_type + + +type_parameter_list - - -ref_method_modifier + + +return_type - - -member_name + + +( - - + + } - - -) - - - -string + + +indexer_declaration - - -method_declaration + + +abstract - - -+ + + +identifier - - -; + + +struct - - -Event + + +return_type - - -public + + +event_declaration - - -( + + +explicitly_typed_local_variable_declarators - - + + ; - - -set + + +decorated_type_parameter - - -statement_list + + +statement - - -class_type + + +internal - - -block + + +property_declaration - - -return + + +] - - -accessor_body + + +indexer_body - - -identifier + + +property_body - - -type + + +A - - -buffer_element_type + + +struct_member_declaration - - -( + + +method_declaration - - + + +type + + + identifier - - -interface_property_declaration + + +field_modifier - - -; + + +field_declaration - - -type + + +set_accessor_declaration ) - - -identifier - - - -} + + +operator_body - - -identifier + + +value - - -identifier + + +struct_member_declaration - - -property_modifier + + +string - - -return_type + + +return_statement - - -struct_member_declaration + + +contextual_keyword - - -int + + +return - - -( + + +identifier - - -volatile + + +indexer_modifier - - -integral_type + + +set - - -accessor_modifier + + +Add - - -operator + + +namespace_declaration - - -class_type + + +[ - - -E + + +struct_member_declaration - - + + identifier - - -{ + + +( - - -} + + +indexer_declarator - - -operator_modifier + + +accessor_body - - -parameter_list + + +} - - -accessor_declarations + + +constructor_modifier - - -; + + +identifier - - -property_modifier + + +identifier - - -block + + +; - - + + identifier - - -, + + +< - - -fixed_size_buffer_declarator + + +struct_member_declaration - - -ref_method_modifier + + +literal - - -constructor_modifier + + +type_parameter - - -property_body + + +expression - - -m + + +] - - -contextual_keyword + + +interface_modifier - - -f2 + + +operator_modifier + + + +operator - - + + } - - -error + + +int - - + + +identifier + + + +"Use·Script·instead" + + + ; - - -struct_body + + +identifier - - -} + + +P - - -private + + +A - - -identifier + + +struct_modifier - - -integral_type + + +ref_method_modifier - - -10 + + +C - - -integral_type + + +abstract - - -struct_member_declaration + + +variable_declarators - - + + member_name - - -indexer_modifier - - - -} + + +declaration_statement - - -{ + + +event_modifier - - -class_type + + +field - - -get_accessor_declaration + + +integral_type - - -identifier + + +accessor_declarations - - -A + + ++ - - -compilation_unit + + +accessor_declarations - - -namespace_member_declaration + + +; - - -{ + + +attribute_section - - -indexer_body + + +get - - -: + + +, - - -identifier + + +type - - -interface_member_declaration + + +{ - - -) + + +type - - -] + + +attribute_arguments - - -int + + +) - - -return + + +10 + + + +struct_member_declaration : - - -operator_declarator + + +identifier - - -integral_type + + +public - - -struct_interfaces + + +expression + + + +type + + + +} + + + +overloadable_binary_operator + + + +method_header identifier - - -parameter_list + + +S - - -property_body + + +identifier - - -struct + + +statement_list - - -qualified_identifier + + +: + + + +identifier + + + +attributes } - - -; + + +private - - -] + + +method_body - - -attribute_name + + +type - - + + ( - - + + identifier - - -identifier + + +; - - -integral_type + + +property_declaration - - -fixed_parameter + + +get_accessor_declaration - - -primary_expression + + +buffer_element_type - - + + identifier - - -namespace_declaration + + +set - - -indexer_modifier + + +public - - -static + + +constant_expression + + + +I method_modifier - - -integral_type + + +A - - -indexer_declarator + + +( - - -positional_argument + + +] - - -argument_name + + +get_accessor_declaration + + + +value - - -interface_accessors + + +field_declaration - - -struct_modifier + + +} - - -interface_method_declaration + + +abstract - - + + struct_member_declaration - - -private + + +literal - - -overloadable_binary_operator + + +) - - -contextual_keyword + + +( - - -false + + +second - - -primary_constraint + + +; - - -value + + +} + + + +where + + + +public + + + +indexer_modifier + + + +fixed_parameter + + + +attribute_name + + + +struct + + + +identifier + + + +attribute_list + + + +{ - - -literal + + +expression + + + +event identifier - - -explicitly_typed_local_variable_declaration + + +int - - -{ + + +public - - -interface_modifier + + +primary_expression - - -identifier + + +} - - -A + + +{ - - -int + + +struct_member_declaration - - -protected + + +block - - -Value + + +accessor_body - - -property_declaration + + +field_modifier - - -field_declaration + + +} - - -[ + + +contextual_keyword - - -{ + + +class_type - - -int + + +get_accessor_declaration - - -identifier + + +type_parameter_constraints_clause - - -constructor_declarator + + +integral_type - - -type + + +protected - - -attribute_argument_expression + + +volatile - - -( + + +class_type - - -0 + + +compilation_unit - - -interface_method_header + + +method_declaration - - -boolean_literal + + +get_accessor_declaration - - -public + + +get - - -value + + +identifier - - -T + + +; - - -Add + + +struct_member_declaration - - -explicitly_typed_local_variable_declarators + + +S - - -} + + +static - - -struct_member_declaration + + +) - - -get_accessor_declaration + + +type_parameter_constraints - - -public + + +class_body - - -identifier + + +1 - - -expression + + +this - - -( + + +local_variable_initializer - - -type_parameter_constraints_clause + + +fixed_parameter - - -} + + +"A" - - -event_declaration + + +method_modifiers - - -) + + +; - - -struct_member_declaration + + +interface_member_declaration - - -class + + +Obsolete - - -type + + +literal - - -{ + + +primary_expression - - -return_statement + + +type - - -first + + +parameter_list - - -identifier + + +block member_access - - -get + + +[ + + + +class_type - - -; + + +int - - -identifier + + +parameter_list - - -accessor_declarations + + +T - - -{ + + +attribute - - -"Use·Script·instead" + + +explicitly_typed_local_variable_declarator - - -type + + +0 - - -P + + +struct_interfaces - - + + identifier - - -statement_list - - - -abstract + + +argument_list - - -A + + +return - - -statement_list + + +local_variable_declaration - - -; + + +string - - + + type - - -P - - - -identifier + + +int - - -constructor_declaration + + +integral_type - - -type + + +binary_operator_declarator - - -interface_type_list + + +( - - -fixed_size_buffer_declarators + + +identifier index - - -> - - - -return_statement - - - -public - - - -namespace_member_declaration + + +boolean_literal - - -identifier + + +property_body - - -positional_argument + + +ref_method_modifier - - -statement + + +struct_member_declaration - - + + int - - -attribute_list + + +prog - - -constant_expression + + +struct_declaration - - -namespace_body + + +fixed_size_buffer_declarator - - -class_declaration + + +> - - -I + + +namespace_member_declaration - - -accessor_body + + +; - - -return_statement + + +property_modifier - - -struct_member_declaration + + +} - - -expression + + +set_accessor_declaration - - -identifier + + +struct_member_declaration - - -return + + +; - - -void + + +invocation_expression - - + + int - - -first - - - -identifier - - - -literal - - - -attribute_arguments - - - -method_body + + +integral_type - - -fixed_parameter + + +fixed_size_buffer_declaration - - -interface + + +{ - - -} + + +member_name - - -class_body + + +namespace_member_declaration - - -variable_declarators + + +{ - - -< + + +interface_declaration positional_argument_list - - -local_variable_initializer + + +identifier - - -method_header + + +class - - -accessor_body + + +E - - -public + + +P - - -get + + +Event - - -accessor_body + + +identifier - - -; + + +identifier - - -fixed_parameter + + +integral_type - - -set_accessor_declaration + + +string - - -explicitly_typed_local_variable_declarator + + +property_body - - -fixed_parameter + + +qualified_identifier - - -= + + +identifier - - -member_name + + +T - - -identifier + + +{ - - -interface_member_declaration + + +t - - -type + + +explicitly_typed_local_variable_declaration - - -[ + + +accessor_body - - -second + + +identifier - - -attribute + + +integral_type - - -declaration_statement + + +operator_declarator - - -} + + +) - - -fixed + + +type - - -{ + + +namespace_body - - -interface_declaration + + +positional_argument - - -public + + +[ - - -, + + +My - - -t + + +error - - -abstract + + +type - - -f1 + + +get - - -field_declaration + + +return - - -method_modifier + + +type - - -interface_body + + +void - - -struct_declaration + + +type - - -decorated_type_parameter + + +interface_body - - -expression + + +namespace - - -; + + +constructor_declaration + + + +I - - + + type - - -field + + +set - - -field_modifier + + +struct_body - - -T + + +interface_type_list - - -variable_declarators + + +fixed_parameter - - -type_parameter_list + + +public - - + + +: + + + +false + + + +parameter_list + + + ; - - -identifier + + +{ + + + += - - -) + + +identifier - - -type_parameter + + +public - - -set + + +member_name - - -parameter_list + + +interface - - -field_modifier + + +literal - - -struct_member_declaration + + +accessor_body - - -namespace + + +{ - - -struct_member_declaration + + +member_name - - + + ; - - -block - - - -property_modifier + + +first - - -identifier + + +f2 - - -C + + +public - - -identifier + + +; - - -constructor_body + + +type - - -I + + +T - - -My + + +fixed - - -accessor_body + + +} - - -binary_operator_declarator + + +first - - -struct_member_declaration + + +property_declaration - - -accessor_declarations + + +A - - -type_parameter_constraints + + +method_header - - -; + + +method_body - - + + identifier - - -primary_expression - - - -"A" + + +) - - -. + + +int - - -prog + + +accessor_modifier - - -A + + +block - - -return_type + + +return_statement - - -public + + +get - - -S + + +{ - - -get_accessor_declaration + + +class_declaration - - -get + + +identifier - - -fixed_size_buffer_declaration + + +; - - -second + + +statement_list - - -block + + +operator_modifier - - -string + + +accessor_declarations - - -fixed_parameter + + +identifier - - -T + + +identifier - - -argument_list + + +constructor_declarator - - -attribute_section + + +attribute_argument_expression - - -attributes + + +return_statement - - -; + + +{ - - -operator_declaration + + +public - - -internal + + +primary_constraint - - -type + + +second \ No newline at end of file