From 9a9f4b7194435ce9cdad0a8c5a9f0d0a8cbc425f Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 5 Feb 2026 16:14:48 -0500 Subject: [PATCH 1/4] support enhanced #line directives --- standard/lexical-structure.md | 60 ++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 44b2fe53e..69d471e89 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -1494,7 +1494,7 @@ corresponds exactly to the lexical processing of a conditional compilation direc Line directives may be used to alter the line numbers and compilation unit names that are reported by a compiler in output such as warnings and errors. These values are also used by caller-info attributes ([§23.5.6](attributes.md#2356-caller-info-attributes)). -> *Note*: Line directives are most commonly used in meta-programming tools that generate C# source code from some other text input. *end note* +> *Note*: Line directives are most commonly used in meta-programming tools that generate C# source code from some other text input. The information these directives provide might be used for debugging purposes and error handling, by allowing mapping of errors back to the original source file, rather than to the generated intermediate file. *end note* ```ANTLR fragment PP_Line @@ -1506,6 +1506,8 @@ fragment PP_Line_Indicator | Decimal_Digit+ | DEFAULT | 'hidden' + | PP_Start_Line_Character PP_Whitespace? '-' PP_Whitespace? PP_End_Line_Character + PP_Whitespace (PP_Character_Offset PP_Whitespace)? PP_Compilation_Unit_Name ; fragment PP_Compilation_Unit_Name @@ -1516,6 +1518,35 @@ fragment PP_Compilation_Unit_Name_Character // Any Input_Character except " : ~('\u000D' | '\u000A' | '\u0085' | '\u2028' | '\u2029' | '"') ; + +fragment PP_Start_Line_Character + : '(' PP_Whitespace? PP_Start_Line PP_Whitespace? ',' PP_Whitespace? + PP_Start_Character PP_Whitespace? ')' + ; +fragment PP_End_Line_Character + : '(' PP_Whitespace? PP_End_Line PP_Whitespace? ',' PP_Whitespace? + PP_End_Character PP_Whitespace? ')' + ; + +fragment PP_Start_Line + : Decimal_Digit+ + ; + +fragment PP_End_Line + : Decimal_Digit+ + ; + +fragment PP_Start_Character + : Decimal_Digit+ + ; + +fragment PP_End_Character + : Decimal_Digit+ + ; + +fragment PP_Character_Offset + : Decimal_Digit+ + ; ``` When no `#line` directives are present, a compiler reports true line numbers and compilation unit names in its output. When processing a `#line` directive that includes a *PP_Line_Indicator* that is not `default`, a compiler treats the line *after* the directive as having the given line number (and compilation unit name, if specified). @@ -1528,6 +1559,33 @@ A `#line hidden` directive has no effect on the compilation unit and line number > *Note*: Although a *PP_Compilation_Unit_Name* might contain text that looks like an escape sequence, such text is not an escape sequence; in this context a ‘`\`’ character simply designates an ordinary backslash character. *end note* +Together, the tokens *Start_Line_Character* '-' *PP_End_Line_Character* specify a span of characters in the so-called mapped file *PP_Compilation_Unit_Name*. + +*PP_Start_Line_Character* represents the start line (*PP_Start_Line*) and column (*PP_Start_Character*) pair of the first character on the line following the directive, which is the mapped file text; for example, `(1,1)`. + +*PP_End_Line_Character* represents the end line (*PP_End_Line*) and column (*PP_End_Character*) pair of the mapped file text; for example, `(3,10)`. + +*PP_Start_Line* and *PP_End_Line* are positive integers that specify line numbers. *PP_Start_Character* and *PP_End_Character* are positive integers that specify UTF-16 character numbers. All four of these numbers are 1-based, meaning that the first line of the mapped file and the first UTF-16 character on each line is assigned number 1. + +By default, the mapped text starts at the first character on the line following the `#line` directive. However, this can be adjusted using *PP_Character_Offset*. If *PP_Character_Offset* is omitted, it defaults to 0; otherwise, it specifies the number of UTF-16 characters to skip in that next line. That number shall be non-negative and less than the length of the line following the `#line` directive. + +The mapping specified by a *PP_Line* is in scope until the following `#line` directive or the end of the compilation unit, whichever comes first. + +> *Example*: Consider the following: +> +> +> ```csharp +> ??? +> ``` +> +> the output produced might be something like the following: +> +> ```console +> ??? +> ``` +> +> *end example* + ### 6.5.9 Nullable directive The nullable directive controls the nullable context, as described below. From b087aab402aa09dfb819b496894d36df70150f6e Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 5 Feb 2026 16:30:34 -0500 Subject: [PATCH 2/4] fix md spaces --- standard/lexical-structure.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 69d471e89..220f0b831 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -1559,7 +1559,7 @@ A `#line hidden` directive has no effect on the compilation unit and line number > *Note*: Although a *PP_Compilation_Unit_Name* might contain text that looks like an escape sequence, such text is not an escape sequence; in this context a ‘`\`’ character simply designates an ordinary backslash character. *end note* -Together, the tokens *Start_Line_Character* '-' *PP_End_Line_Character* specify a span of characters in the so-called mapped file *PP_Compilation_Unit_Name*. +Together, the tokens *Start_Line_Character* '-' *PP_End_Line_Character* specify a span of characters in the so-called mapped file *PP_Compilation_Unit_Name*. *PP_Start_Line_Character* represents the start line (*PP_Start_Line*) and column (*PP_Start_Character*) pair of the first character on the line following the directive, which is the mapped file text; for example, `(1,1)`. @@ -1569,7 +1569,7 @@ Together, the tokens *Start_Line_Character* '-' *PP_End_Line_Character* specify By default, the mapped text starts at the first character on the line following the `#line` directive. However, this can be adjusted using *PP_Character_Offset*. If *PP_Character_Offset* is omitted, it defaults to 0; otherwise, it specifies the number of UTF-16 characters to skip in that next line. That number shall be non-negative and less than the length of the line following the `#line` directive. -The mapping specified by a *PP_Line* is in scope until the following `#line` directive or the end of the compilation unit, whichever comes first. +The mapping specified by a *PP_Line* is in scope until the following `#line` directive or the end of the compilation unit, whichever comes first. > *Example*: Consider the following: > @@ -1577,7 +1577,7 @@ The mapping specified by a *PP_Line* is in scope until the following `#line` dir > ```csharp > ??? > ``` -> +> > the output produced might be something like the following: > > ```console From 10d3e2eca90d52e613986095bbde36f25b627bed Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Thu, 5 Feb 2026 16:34:09 -0500 Subject: [PATCH 3/4] fix place-holder example --- standard/lexical-structure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 220f0b831..97761fd8b 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -1575,7 +1575,7 @@ The mapping specified by a *PP_Line* is in scope until the following `#line` dir > > > ```csharp -> ??? +> // exxample goes here > ``` > > the output produced might be something like the following: From 25e955aeb0ce3fa324536e104348624953d9ae58 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Fri, 13 Feb 2026 12:12:01 -0500 Subject: [PATCH 4/4] disable incomplete example extraction --- standard/lexical-structure.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 97761fd8b..0a7191757 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -1573,9 +1573,9 @@ The mapping specified by a *PP_Line* is in scope until the following `#line` dir > *Example*: Consider the following: > -> +> > ```csharp -> // exxample goes here +> // example goes here > ``` > > the output produced might be something like the following: