From 6a492bc3ebb6826a9ffc140b7218c24ae3c5c08b Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 22 Jan 2026 12:01:11 -0500 Subject: [PATCH 1/3] Add support for file-scoped namespaces --- standard/basic-concepts.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index eecbb6ba7..aa5585251 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -245,7 +245,7 @@ A declaration defines a name in the ***declaration space*** to which the declara There are several different types of declaration spaces, as described in the following. - 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. +- Within all compilation units of a program, *compilation_unit_body*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, 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. @@ -772,9 +772,9 @@ The ***scope*** of a name is the region of program text within which it is possi > *Note*: It may not be possible to access the hidden outer name from the inner scope because there is no way of qualifying it, such as with type parameters on nested type declarations. *end note* - The scope of a namespace member declared by a *namespace_member_declaration* ([§14.6](namespaces.md#146-namespace-member-declarations)) with no enclosing *namespace_declaration* is the entire program text. -- The scope of a namespace member declared by a *namespace_member_declaration* within a *namespace_declaration* whose fully qualified name is `N`, is the *namespace_body* of every *namespace_declaration* whose fully qualified name is `N` or starts with `N`, followed by a period. -- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit* or *namespace_body* in which it occurs. -- The scope of a name defined or imported by a *using_directive* ([§14.5](namespaces.md#145-using-directives)) extends over the *global_attributes* and *namespace_member_declaration*s of the *compilation_unit* or *namespace_body* in which the *using_directive* occurs. A *using_directive* may make zero or more namespace or type names available within a particular *compilation_unit* or *namespace_body*, but does not contribute any new members to the underlying declaration space. In other words, a *using_directive* is not transitive but rather affects only the *compilation_unit* or *namespace_body* in which it occurs. +- The scope of a namespace member declared by a *compilation_unit_body* whose fully qualified name is `N`, is every *compilation_unit_body* whose fully qualified name is `N` or starts with `N`, followed by a period. +- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *using_directive*s, *global_attributes*, and *compilation_unit_body* of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* in which it occurs. +- The scope of a name defined or imported by a *using_directive* ([§14.5](namespaces.md#145-using-directives)) extends over the *global_attributes* and *compilation_unit_body* of the *compilation_unit* or *namespace_body* in which the *using_directive* occurs. A *using_directive* may make zero or more namespace or type names available within a particular *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* but does not contribute any new members to the underlying declaration space. In other words, a *using_directive* is not transitive but rather affects only the *compilation_unit*, *namespace_body*, and *file_scoped_namespace_declaration* in which it occurs. - The scope of a type parameter declared by a *type_parameter_list* on a *class_declaration* ([§15.2](classes.md#152-class-declarations)) is the *class_base*, *type_parameter_constraints_clause*s, and *class_body* of that *class_declaration*. > *Note*: Unlike members of a class, this scope does not extend to derived classes. *end note* - The scope of a type parameter declared by a *type_parameter_list* on a *struct_declaration* ([§16.2](structs.md#162-struct-declarations)) is the *struct_interfaces*, *type_parameter_constraints_clause*s, and *struct_body* of that *struct_declaration*. From e78132df3cb178a58bfe6cb9ba3d7f4c229baa37 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 22 Jan 2026 12:26:16 -0500 Subject: [PATCH 2/3] Add support for file-scoped namespaces --- standard/namespaces.md | 69 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/standard/namespaces.md b/standard/namespaces.md index d5145d5a7..c095b0fd4 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -8,24 +8,30 @@ Using directives ([§14.5](namespaces.md#145-using-directives)) are provided to ## 14.2 Compilation units -A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input. +A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by a *compilation_unit_body*. A *compilation_unit_body* can either be zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s, or a *file_scoped_namespace_declaration*. The *compilation_unit* defines the overall structure of the input. ```ANTLR compilation_unit - : extern_alias_directive* using_directive* global_attributes? - statement_list* namespace_member_declaration* + : extern_alias_directive* using_directive* global_attributes? compilation_unit_body + ; + +compilation_unit_body + : statement_list* namespace_member_declaration* + | file_scoped_namespace_declaration ; ``` A C# program consists of one or more compilation units. When a C# program is compiled, all of the compilation units are processed together. Thus, compilation units can depend on each other, possibly in a circular fashion. -The *extern_alias_directive*s of a compilation unit affect the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units. +The *extern_alias_directive*s of a compilation unit affect the *using_directive*s, *global_attributes* and *compilation_unit_body* of that compilation unit, but have no effect on other compilation units. -The *using_directive*s of a compilation unit affect the *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units. +The *using_directive*s of a compilation unit affect the *global_attributes* and *compilation_unit_body* of that compilation unit, but have no effect on other compilation units. The *global_attributes* ([§23.3](attributes.md#233-attribute-specification)) of a compilation unit permit the specification of attributes for the target assembly and module. Assemblies and modules act as physical containers for types. An assembly may consist of several physically separate modules. -The *namespace_member_declaration*s of each compilation unit of a program contribute members to a single declaration space called the global namespace. +The *namespace_member_declaration*s or *file_scoped_namespace_declaration* of each compilation unit of a program contribute members to a single declaration space called the global namespace. + +A *file_scoped_namespace_declaration* contributes members corresponding to the *namespace_declaration* to which it is semantically equivalent ([§14.3](namespaces.md#143-namespace-declarations)). > *Example*: > @@ -43,13 +49,18 @@ The *namespace_member_declaration*s of each compilation unit of a program contri ## 14.3 Namespace declarations -A *namespace_declaration* consists of the keyword namespace, followed by a namespace name and body, optionally followed by a semicolon. +A *namespace_declaration* consists of the keyword namespace, followed by a namespace name and body, optionally followed by a semicolon. A *file_scoped_namespace_declaration* consists of the keyword `namespace`, followed by a namespace name, a semicolon, and an optional list of *extern_alias_directive*s, *using_directive*s and *type_declaration*s. ```ANTLR namespace_declaration : 'namespace' qualified_identifier namespace_body ';'? ; +file_scoped_namespace_declaration + : 'namespace' qualified_identifier ';' extern_alias_directive* using_directive* + type_declaration* + ; + qualified_identifier : identifier ('.' identifier)* ; @@ -62,11 +73,15 @@ namespace_body A *namespace_declaration* may occur as a top-level declaration in a *compilation_unit* or as a member declaration within another *namespace_declaration*. When a *namespace_declaration* occurs as a top-level declaration in a *compilation_unit*, the namespace becomes a member of the global namespace. When a *namespace_declaration* occurs within another *namespace_declaration*, the inner namespace becomes a member of the outer namespace. In either case, the name of a namespace shall be unique within the containing namespace. +A *file_scoped_namespace_declaration* may only occur as a top-level declaration in a *compilation_unit*. As such, the declared namespace becomes a member of the global namespace. + Namespaces are implicitly `public` and the declaration of a namespace cannot include any access modifiers. Within a *namespace_body*, the optional *using_directive*s import the names of other namespaces, types and members, allowing them to be referenced directly instead of through qualified names. The optional *namespace_member_declaration*s contribute members to the declaration space of the namespace. Note that all *using_directive*s shall appear before any member declarations. -The *qualified_identifier* of a *namespace_declaration* may be a single identifier or a sequence of identifiers separated by “`.`” tokens. The latter form permits a program to define a nested namespace without lexically nesting several namespace declarations. +Within a *file_scoped_namespace_declaration*, the optional *using_directive*s import the names of other namespaces, types and members, allowing them to be referenced directly instead of through qualified names. The optional *type_declaration*s contribute members to the declaration space of the namespace. Note that all *using_directive*s shall appear before any type declarations. + +The *qualified_identifier* of a *namespace_declaration* and *file_scoped_namespace_declaration* may be a single identifier or a sequence of identifiers separated by “`.`” tokens. The latter form permits a program to define a nested namespace without lexically nesting several namespace declarations. > *Example*: > @@ -116,6 +131,40 @@ Namespaces are open-ended, and two namespace declarations with the same fully qu > > *end example* +A *file_scoped_namespace_declaration* permits a namespace declaration to be written without an accompanying `{ … }` block. + +> *Example*: +> +> +> ```csharp +> namespace Name; +> using System; +> class C +> { +> } +> ``` +> +> is semantically equivalent to +> +> +> ```csharp +> namespace Name +> { +> using System; +> class C +> { +> } +> } +> ``` +> +> *end example* + +A *file_scoped_namespace_declaration* is treated the same as a *namespace_declaration* at the same location in the *compilation_unit* with the same *qualified_identifier*. The *extern_alias_directive*s, *using_directive*s and *type_declaration*s of that *file_scoped_namespace_declaration* act as if they were declared in the same order inside the *namespace_body* of that *namespace_declaration*. + +> *Note*: As determined by the grammar, a compilation unit cannot contain both a *file_scoped_namespace_declaration* and a *namespace_declaration*. It cannot contain multiple *file_scoped_namespace_declaration*s. It cannot contain both a *file_scoped_namespace_declaration* and any top level *statement*s. *type_declaration*s cannot precede a *file_scoped_namespace_declaration*. *end note* + +Different compilation units may contribute to the same namespace using either or both of the *namespace_member_declaration* or *file_scoped_namespace_declaration* syntax. + ## 14.4 Extern alias directives An *extern_alias_directive* introduces an identifier that serves as an alias for a namespace. The specification of the aliased namespace is external to the source code of the program and applies also to nested namespaces of the aliased namespace. @@ -126,7 +175,7 @@ extern_alias_directive ; ``` -The scope of an *extern_alias_directive* extends over the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. +The scope of an *extern_alias_directive* is described in [§7.7.1]( basic-concepts.md#771-general). Within a compilation unit or namespace body that contains an *extern_alias_directive*, the identifier introduced by the *extern_alias_directive* can be used to reference the aliased namespace. It is a compile-time error for the *identifier* to be the word `global`. @@ -175,7 +224,7 @@ A *using_namespace_directive* ([§14.5.3](namespaces.md#1453-using-namespace-dir A *using_static_directive* ([§14.5.4](namespaces.md#1454-using-static-directives)) imports the nested types and static members of a type. -The scope of a *using_directive* extends over the *namespace_member_declarations* of its immediately containing compilation unit or namespace body. The scope of a *using_directive* specifically does not include its peer *using_directive*s. Thus, peer *using_directive*s do not affect each other, and the order in which they are written is insignificant. In contrast, the scope of an *extern_alias_directive* includes the *using_directive*s defined in the same compilation unit or namespace body. +The scope of a *using_directive* is described in [§7.7.1]( basic-concepts.md#771-general). ### 14.5.2 Using alias directives From 59ede4cef508847dfe35685c8593072f268ab8f6 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 22 Jan 2026 12:44:37 -0500 Subject: [PATCH 3/3] fix formatting --- standard/namespaces.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/standard/namespaces.md b/standard/namespaces.md index c095b0fd4..ff8b4cffa 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -134,7 +134,7 @@ Namespaces are open-ended, and two namespace declarations with the same fully qu A *file_scoped_namespace_declaration* permits a namespace declaration to be written without an accompanying `{ … }` block. > *Example*: -> +> > > ```csharp > namespace Name; @@ -143,9 +143,9 @@ A *file_scoped_namespace_declaration* permits a namespace declaration to be writ > { > } > ``` -> +> > is semantically equivalent to -> +> > > ```csharp > namespace Name @@ -156,9 +156,9 @@ A *file_scoped_namespace_declaration* permits a namespace declaration to be writ > } > } > ``` -> +> > *end example* - + A *file_scoped_namespace_declaration* is treated the same as a *namespace_declaration* at the same location in the *compilation_unit* with the same *qualified_identifier*. The *extern_alias_directive*s, *using_directive*s and *type_declaration*s of that *file_scoped_namespace_declaration* act as if they were declared in the same order inside the *namespace_body* of that *namespace_declaration*. > *Note*: As determined by the grammar, a compilation unit cannot contain both a *file_scoped_namespace_declaration* and a *namespace_declaration*. It cannot contain multiple *file_scoped_namespace_declaration*s. It cannot contain both a *file_scoped_namespace_declaration* and any top level *statement*s. *type_declaration*s cannot precede a *file_scoped_namespace_declaration*. *end note*