From 655f1943b9593234a1b023a90a8a49d637416064 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 18:13:28 +0100 Subject: [PATCH 01/14] [C#] Rename string contexts This commit ... 1. removes `_literal` suffix from normal raw-strings to match context naming scheme with `inside_string` and `inside_long_string`. 2. renames `_long` to `_verbatim` as C# spec uses the later term for string literals starting with `@"` --- C#/C#.sublime-syntax | 86 +++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 0cbeaffc28..3ef8df8ff6 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1930,47 +1930,51 @@ contexts: - include: strings strings: + # literal raw strings - match: '(""""+)' scope: punctuation.definition.string.begin.cs - push: inside_raw_string_literal + push: inside_raw_string - match: '"""' scope: punctuation.definition.string.begin.cs push: - - inside_triple_quoted_raw_string_literal - - inside_triple_quoted_raw_string_literal_syntax + - inside_triple_quoted_raw_string + - inside_triple_quoted_raw_string_syntax + # literal quoted strings - match: '"' scope: punctuation.definition.string.begin.cs push: inside_string - # interpolated strings + # interpolated raw format strings - match: '\$("""+)' scope: punctuation.definition.string.begin.cs - push: inside_raw_format_string + push: inside_raw_format_string_1 - match: '\$\$("""+)' scope: punctuation.definition.string.begin.cs push: inside_raw_format_string_2 + # interpolated raw verbatim format strings - match: '@\$("""+)' scope: punctuation.definition.string.begin.cs - push: inside_raw_format_string_literal + push: inside_raw_verbatim_format_string_1 - match: '@\$\$("""+)' scope: punctuation.definition.string.begin.cs push: inside_raw_format_string_literal_2 + # interpolated quoted format strings - match: '\$"' scope: punctuation.definition.string.begin.cs push: inside_format_string - # multi-line strings + # literal verbatim strings - match: '@"' scope: punctuation.definition.string.begin.cs push: - - inside_long_string - - inside_long_string_syntax - # interpolated multi-line strings - - match: '(@\$|\$@)"' + - inside_verbatim_string + - inside_verbatim_string_syntax + # interpolated verbatim format strings + - match: '(?:@\$|\$@)"' scope: punctuation.definition.string.begin.cs push: - - inside_long_format_string - - inside_long_format_string_syntax + - inside_verbatim_format_string + - inside_verbatim_format_string_syntax - inside_raw_string_literal: + inside_raw_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.triple.cs - match: '\1' @@ -1980,7 +1984,7 @@ contexts: - include: string_placeholders - include: extended_string_placeholders - inside_triple_quoted_raw_string_literal: + inside_triple_quoted_raw_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.triple.cs - match: '"""' @@ -1990,7 +1994,7 @@ contexts: - include: string_placeholders - include: extended_string_placeholders - inside_triple_quoted_raw_string_literal_syntax: + inside_triple_quoted_raw_string_syntax: - meta_include_prototype: false - match: (?={{sql_indicator}}) set: scope:source.sql @@ -2026,7 +2030,7 @@ contexts: scope: invalid.illegal.unclosed-string.cs pop: true - inside_raw_format_string: + inside_raw_format_string_1: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - match: '\1' @@ -2036,7 +2040,7 @@ contexts: - include: string_placeholder_escape - include: format_string_interpolation - inside_raw_format_string_literal: + inside_raw_verbatim_format_string_1: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - match: '\1' @@ -2096,34 +2100,34 @@ contexts: - include: string_placeholder_format - include: line_of_code_in - inside_long_format_string: + inside_verbatim_format_string: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs - - include: long_string_escaped + - include: verbatim_string_escaped - match: '"' scope: punctuation.definition.string.end.cs pop: true - include: string_placeholder_escape - match: \{ scope: punctuation.section.interpolation.begin.cs - push: inside_long_format_string_interpolation + push: inside_verbatim_format_string_interpolation - inside_long_format_string_syntax: + inside_verbatim_format_string_syntax: - meta_include_prototype: false - match: (?={{sql_indicator}}) set: scope:source.sql with_prototype: - - include: long_string_escaped + - include: verbatim_string_escaped - match: (?=") pop: true - include: string_placeholder_escape - match: \{ scope: punctuation.section.interpolation.begin.cs - push: inside_long_format_string_interpolation + push: inside_verbatim_format_string_interpolation - match: (?=\S) pop: true - inside_long_format_string_interpolation: + inside_verbatim_format_string_interpolation: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs @@ -2131,7 +2135,7 @@ contexts: scope: punctuation.section.interpolation.end.cs pop: true - include: string_replacement_width - - include: long_string_placeholder_format + - include: verbatim_string_placeholder_format - include: line_of_code_in string_placeholder_escape: @@ -2163,18 +2167,18 @@ contexts: - match: '[^"}]+' scope: invalid.illegal.unexpected-character-in-placeholder.cs - extended_long_string_placeholders: + extended_verbatim_string_placeholders: - match: '(\{)(\d+)' captures: 1: punctuation.definition.placeholder.begin.cs 2: meta.number.integer.decimal.cs constant.numeric.value.cs - push: inside_extended_long_string_placeholder + push: inside_extended_verbatim_string_placeholder - inside_extended_long_string_placeholder: + inside_extended_verbatim_string_placeholder: - meta_scope: constant.other.placeholder.cs - include: string_placeholder_end - include: string_placeholder_width - - include: long_string_placeholder_format + - include: verbatim_string_placeholder_format - match: '[^"}]+' scope: invalid.illegal.unexpected-character-in-placeholder.cs @@ -2226,19 +2230,19 @@ contexts: - match: '\{' scope: invalid.illegal.unescaped-placeholder.cs - long_string_placeholder_format: + verbatim_string_placeholder_format: - match: ':(?="(?!"))' scope: invalid.illegal.unclosed-string-placeholder.cs pop: true - match: ':' scope: punctuation.separator.cs - push: inside_long_string_placeholder_format + push: inside_verbatim_string_placeholder_format - inside_long_string_placeholder_format: + inside_verbatim_string_placeholder_format: - meta_scope: meta.format-spec.cs - meta_content_scope: constant.other.format-spec.cs - include: string_placeholder_escape - - include: long_string_escaped + - include: verbatim_string_escaped - match: (?=\}) pop: true - match: \\(?:""|[^"]) @@ -2249,26 +2253,26 @@ contexts: - match: \{ scope: invalid.illegal.unescaped-placeholder.cs - inside_long_string: + inside_verbatim_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.double.raw.cs - - include: long_string_escaped + - include: verbatim_string_escaped - match: '"' scope: punctuation.definition.string.end.cs pop: true - include: string_placeholders - - include: extended_long_string_placeholders + - include: extended_verbatim_string_placeholders - inside_long_string_syntax: + inside_verbatim_string_syntax: - meta_include_prototype: false - match: (?={{sql_indicator}}) set: scope:source.sql with_prototype: - - include: long_string_escaped + - include: verbatim_string_escaped - match: (?=") pop: true - include: string_placeholders - - include: extended_long_string_placeholders + - include: extended_verbatim_string_placeholders - match: (?=\S) pop: true @@ -2281,7 +2285,7 @@ contexts: - match: \\ scope: invalid.illegal.lone-escape.cs - long_string_escaped: + verbatim_string_escaped: - match: '""' scope: constant.character.escape.cs From 52af7461a437b69c39cce591a26e7495a6b9e46f Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 16:14:51 +0100 Subject: [PATCH 02/14] [C#] Remove invalid raw string literal This commit removes patterns of an unsupported raw string literals. Verbatim strings may start with escaped quotes `""`, which makes them look like verbatim raw string literals. C# 11 and 12 raise compiler error, only if `@` is combined with multiple `$` chars, such as `@$$" ... "`. --- C#/C#.sublime-syntax | 25 ---------------------- C#/tests/syntax_test_C#11.cs | 40 +++++++++++++++++++++++------------- 2 files changed, 26 insertions(+), 39 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 3ef8df8ff6..2ac967b302 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1950,13 +1950,6 @@ contexts: - match: '\$\$("""+)' scope: punctuation.definition.string.begin.cs push: inside_raw_format_string_2 - # interpolated raw verbatim format strings - - match: '@\$("""+)' - scope: punctuation.definition.string.begin.cs - push: inside_raw_verbatim_format_string_1 - - match: '@\$\$("""+)' - scope: punctuation.definition.string.begin.cs - push: inside_raw_format_string_literal_2 # interpolated quoted format strings - match: '\$"' scope: punctuation.definition.string.begin.cs @@ -2040,15 +2033,6 @@ contexts: - include: string_placeholder_escape - include: format_string_interpolation - inside_raw_verbatim_format_string_1: - - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - - match: '\1' - scope: punctuation.definition.string.end.cs - pop: true - - include: string_placeholder_escape - - include: format_string_interpolation - format_string_interpolation: - match: \{ scope: punctuation.section.interpolation.begin.cs @@ -2075,15 +2059,6 @@ contexts: - include: string_placeholder_escape - include: format_string_interpolation_2 - inside_raw_format_string_literal_2: - - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - - match: '\1' - scope: punctuation.definition.string.end.cs - pop: true - - include: string_placeholder_escape - - include: format_string_interpolation_2 - format_string_interpolation_2: - match: \{\{ scope: punctuation.section.interpolation.begin.cs diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 220b2e05c3..c8f41b54b0 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -50,19 +50,29 @@ You are at {{{Longitude}} \t {{Latitude}}} ///^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.end /// ^ punctuation.terminator.statement - string +// Note: Verbatim strings may look like raw strings when starting with escaped double-quotes var location = @$""" -/// ^^^^^ meta.string.interpolated string.quoted.triple -/// ^^^^ punctuation.definition.string.begin -/// ^ - invalid +/// ^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^ punctuation.definition.string.begin.cs +/// ^^ constant.character.escape.cs You are at {{{Longitude}} \t {{Latitude}}} -///^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^^^^^^^^^^ meta.string.interpolated meta.interpolation - string -/// ^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^ - constant.character.escape +///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^ constant.character.escape.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ variable.other.cs +/// ^ punctuation.section.interpolation.end.cs +/// ^^^^^ - constant +/// ^^ constant.character.escape.cs +/// ^^ constant.character.escape.cs +/// ^ - constant """; -/// <- meta.string.interpolated string.quoted.triple -///^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.end -/// ^ punctuation.terminator.statement - string +/// <- meta.string.interpolated.cs string.quoted.double.raw.cs +///^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +///^^ constant.character.escape.cs +/// ^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y)} from the origin"""; /// ^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin @@ -128,11 +138,13 @@ The following example shows how newlines can improve the readability of an expre /// ^^ constant.character.escape /// ^^^^^^^^^^^^^^^^^ - constant - string s2 = @$$"""He said, ""This is the last \u0063hance\x0021"""; -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^^^^^ punctuation.definition.string.begin -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant +/// ^ invalid.illegal.reserved-char.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple +/// ^^^^^ punctuation.definition.string.begin +/// ^^ - constant.character +/// ^^^^^^ constant.character.escape.cs +/// ^^^^^^ constant.character.escape.cs /// ^^^ punctuation.definition.string.end public class C2 { From d56a46bf64a1b8e299bab629071aa6c2711d8534 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 17:51:39 +0100 Subject: [PATCH 03/14] [C#] Fix escapes in raw strings This commit removes `string_escaped` import from raw strings as those are interpreted literal. --- C#/C#.sublime-syntax | 6 +----- C#/tests/syntax_test_C#11.cs | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 2ac967b302..1d517c0437 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1973,7 +1973,6 @@ contexts: - match: '\1' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped - include: string_placeholders - include: extended_string_placeholders @@ -1983,7 +1982,6 @@ contexts: - match: '"""' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped - include: string_placeholders - include: extended_string_placeholders @@ -2000,10 +1998,10 @@ contexts: inside_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.double.cs - - include: string_escaped - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_escaped - include: string_placeholders - include: extended_string_placeholders - match: $\n? @@ -2029,7 +2027,6 @@ contexts: - match: '\1' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped - include: string_placeholder_escape - include: format_string_interpolation @@ -2055,7 +2052,6 @@ contexts: - match: '\1' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped - include: string_placeholder_escape - include: format_string_interpolation_2 diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index c8f41b54b0..efd2ec0fe1 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -11,6 +11,9 @@ more than others. Some should start at the first column. Some have "quoted text" in them. /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple - punctuation + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant.character - invalid """; /// ^^^ string.quoted.triple punctuation.definition.string.end @@ -19,7 +22,8 @@ Some have "quoted text" in them. embedded quote characters in a sequence. That's why it starts and ends with five double quotes. -You could extend this example with as many embedded quotes as needed for your text. + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant.character - invalid """"" // - no semi-colon on the line above @@ -27,13 +31,14 @@ with five double quotes. /// <- storage.type.variable /// ^^^^^^^^ variable.other /// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin - You are at {{{Longitude}}, {{Latitude}}} + You are at {{{Longitude}} \t {{Latitude}}} /// ^^ meta.string.interpolated string.quoted.triple constant.character.escape /// ^ - constant /// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^ - constant +/// ^^ - constant +/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape +/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape +/// ^ - constant """; var location = $""" @@ -44,7 +49,7 @@ You are at {{{Longitude}} \t {{Latitude}}} ///^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple /// ^^^^^^^^^^^ meta.string.interpolated meta.interpolation - string /// ^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^ constant.character.escape +/// ^^ - constant.character """; /// <- meta.string.interpolated string.quoted.triple ///^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.end @@ -143,8 +148,7 @@ The following example shows how newlines can improve the readability of an expre /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple /// ^^^^^ punctuation.definition.string.begin /// ^^ - constant.character -/// ^^^^^^ constant.character.escape.cs -/// ^^^^^^ constant.character.escape.cs +/// ^^^^^^^^^^^^^^^^^ - constant /// ^^^ punctuation.definition.string.end public class C2 { From b4629a6ab7f80f551fe45584ebf38f90cd8236dc Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 10:14:26 +0200 Subject: [PATCH 04/14] [C#] Rename escape sequence contexts This commit renames `_escaped` to `_escapes` in context names, to denote their no-popping behavior via plural. --- C#/C#.sublime-syntax | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 1d517c0437..43f0a789d6 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2001,7 +2001,7 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped + - include: string_escapes - include: string_placeholders - include: extended_string_placeholders - match: $\n? @@ -2014,8 +2014,8 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true - - include: string_escaped - - include: string_placeholder_escape + - include: string_escapes + - include: string_placeholder_escapes - include: format_string_interpolation - match: $\n? scope: invalid.illegal.unclosed-string.cs @@ -2027,7 +2027,7 @@ contexts: - match: '\1' scope: punctuation.definition.string.end.cs pop: true - - include: string_placeholder_escape + - include: string_placeholder_escapes - include: format_string_interpolation format_string_interpolation: @@ -2052,7 +2052,7 @@ contexts: - match: '\1' scope: punctuation.definition.string.end.cs pop: true - - include: string_placeholder_escape + - include: string_placeholder_escapes - include: format_string_interpolation_2 format_string_interpolation_2: @@ -2074,11 +2074,11 @@ contexts: inside_verbatim_format_string: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs - - include: verbatim_string_escaped + - include: verbatim_string_escapes - match: '"' scope: punctuation.definition.string.end.cs pop: true - - include: string_placeholder_escape + - include: string_placeholder_escapes - match: \{ scope: punctuation.section.interpolation.begin.cs push: inside_verbatim_format_string_interpolation @@ -2088,10 +2088,10 @@ contexts: - match: (?={{sql_indicator}}) set: scope:source.sql with_prototype: - - include: verbatim_string_escaped + - include: verbatim_string_escapes - match: (?=") pop: true - - include: string_placeholder_escape + - include: string_placeholder_escapes - match: \{ scope: punctuation.section.interpolation.begin.cs push: inside_verbatim_format_string_interpolation @@ -2109,12 +2109,12 @@ contexts: - include: verbatim_string_placeholder_format - include: line_of_code_in - string_placeholder_escape: + string_placeholder_escapes: - match: '\{\{|\}\}' scope: constant.character.escape.cs string_placeholders: - - include: string_placeholder_escape + - include: string_placeholder_escapes - match: \{\h{8}-(?:\h{4}-){3}\h{12}\} scope: constant.other.guid.cs - match: '(\{)(\d+)(?=")' @@ -2191,8 +2191,8 @@ contexts: inside_string_placeholder_format: - meta_scope: meta.format-spec.cs - meta_content_scope: constant.other.format-spec.cs - - include: string_placeholder_escape - - include: string_escaped + - include: string_placeholder_escapes + - include: string_escapes - match: '(?=\})' pop: true - match: '(?:[^}"\\](?:\\.)*)+(?=")' @@ -2212,8 +2212,8 @@ contexts: inside_verbatim_string_placeholder_format: - meta_scope: meta.format-spec.cs - meta_content_scope: constant.other.format-spec.cs - - include: string_placeholder_escape - - include: verbatim_string_escaped + - include: string_placeholder_escapes + - include: verbatim_string_escapes - match: (?=\}) pop: true - match: \\(?:""|[^"]) @@ -2227,7 +2227,7 @@ contexts: inside_verbatim_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.double.raw.cs - - include: verbatim_string_escaped + - include: verbatim_string_escapes - match: '"' scope: punctuation.definition.string.end.cs pop: true @@ -2239,7 +2239,7 @@ contexts: - match: (?={{sql_indicator}}) set: scope:source.sql with_prototype: - - include: verbatim_string_escaped + - include: verbatim_string_escapes - match: (?=") pop: true - include: string_placeholders @@ -2247,16 +2247,13 @@ contexts: - match: (?=\S) pop: true - escaped: + string_escapes: - match: '{{escaped_char}}' scope: constant.character.escape.cs - - string_escaped: - - include: escaped - match: \\ scope: invalid.illegal.lone-escape.cs - verbatim_string_escaped: + verbatim_string_escapes: - match: '""' scope: constant.character.escape.cs From e37f4392f034ddc4fe681d907930bf85410d1ec2 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 16:23:08 +0100 Subject: [PATCH 05/14] [C#] Fix raw format strings This commit ... 1. restricts allowed number of subsequent `{` or `}`, depending on amount of `$` a raw string literal starts with. 2. adds dedicated `raw_string_placeholder_format` without `string_escapes` context. --- C#/C#.sublime-syntax | 155 +++++++++----- C#/tests/syntax_test_C#11.cs | 248 ++++++++++++++++++++--- C#/tests/syntax_test_GeneralStructure.cs | 4 + 3 files changed, 320 insertions(+), 87 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 43f0a789d6..3ec4140648 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1967,34 +1967,6 @@ contexts: - inside_verbatim_format_string - inside_verbatim_format_string_syntax - inside_raw_string: - - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.triple.cs - - match: '\1' - scope: punctuation.definition.string.end.cs - pop: true - - include: string_placeholders - - include: extended_string_placeholders - - inside_triple_quoted_raw_string: - - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.triple.cs - - match: '"""' - scope: punctuation.definition.string.end.cs - pop: true - - include: string_placeholders - - include: extended_string_placeholders - - inside_triple_quoted_raw_string_syntax: - - meta_include_prototype: false - - match: (?={{sql_indicator}}) - set: scope:source.sql - with_prototype: - - match: (?=""") - pop: true - - match: (?=\S) - pop: true - inside_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.double.cs @@ -2016,59 +1988,102 @@ contexts: pop: true - include: string_escapes - include: string_placeholder_escapes - - include: format_string_interpolation + - match: \{ + scope: punctuation.section.interpolation.begin.cs + push: inside_format_string_interpolation - match: $\n? scope: invalid.illegal.unclosed-string.cs pop: true + inside_format_string_interpolation: + - clear_scopes: 1 + - meta_scope: meta.interpolation.cs + - meta_content_scope: source.cs + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true + - match: (?=") + pop: true + - include: string_interpolation_width + - include: string_placeholder_format + - include: line_of_code_in + + inside_raw_string: + - meta_include_prototype: false + - meta_scope: meta.string.cs string.quoted.triple.cs + - match: \1 + scope: punctuation.definition.string.end.cs + pop: true + - include: string_placeholders + - include: extended_raw_string_placeholders + + inside_triple_quoted_raw_string: + - meta_include_prototype: false + - meta_scope: meta.string.cs string.quoted.triple.cs + - match: '"""' + scope: punctuation.definition.string.end.cs + pop: true + - include: string_placeholders + - include: extended_raw_string_placeholders + + inside_triple_quoted_raw_string_syntax: + - meta_include_prototype: false + - match: (?={{sql_indicator}}) + set: scope:source.sql + with_prototype: + - match: (?=""") + pop: true + - match: (?=\S) + pop: true + inside_raw_format_string_1: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - - match: '\1' + - match: \1 scope: punctuation.definition.string.end.cs pop: true - - include: string_placeholder_escapes - - include: format_string_interpolation - - format_string_interpolation: + - match: \{{2,}|\}{1,} + scope: invalid.illegal.unescaped-placeholder.cs - match: \{ scope: punctuation.section.interpolation.begin.cs - push: inside_format_string_interpolation + push: inside_raw_format_string_interpolation_1 - inside_format_string_interpolation: + inside_raw_format_string_interpolation_1: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: '\}' + - match: \} scope: punctuation.section.interpolation.end.cs pop: true - - include: string_replacement_width - - include: string_placeholder_format + - match: (?=") + pop: true + - include: string_interpolation_width + - include: raw_string_placeholder_format - include: line_of_code_in inside_raw_format_string_2: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs - - match: '\1' + - match: \1 scope: punctuation.definition.string.end.cs pop: true - - include: string_placeholder_escapes - - include: format_string_interpolation_2 - - format_string_interpolation_2: - - match: \{\{ + - match: \{{2}(?!\{) scope: punctuation.section.interpolation.begin.cs - push: inside_format_string_interpolation_2 + push: inside_raw_format_string_interpolation_2 + - match: \}{2,} + scope: invalid.illegal.unescaped-placeholder.cs - inside_format_string_interpolation_2: + inside_raw_format_string_interpolation_2: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: '\}\}' + - match: \}{2} scope: punctuation.section.interpolation.end.cs pop: true - - include: string_replacement_width - - include: string_placeholder_format + - match: (?=") + pop: true + - include: string_interpolation_width + - include: raw_string_placeholder_format - include: line_of_code_in inside_verbatim_format_string: @@ -2102,10 +2117,12 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: '\}' + - match: \} scope: punctuation.section.interpolation.end.cs pop: true - - include: string_replacement_width + - match: (?=") + pop: true + - include: string_interpolation_width - include: verbatim_string_placeholder_format - include: line_of_code_in @@ -2138,6 +2155,21 @@ contexts: - match: '[^"}]+' scope: invalid.illegal.unexpected-character-in-placeholder.cs + extended_raw_string_placeholders: + - match: '(\{)(\d+)' + captures: + 1: punctuation.definition.placeholder.begin.cs + 2: meta.number.integer.decimal.cs constant.numeric.value.cs + push: inside_extended_raw_string_placeholder + + inside_extended_raw_string_placeholder: + - meta_scope: constant.other.placeholder.cs + - include: string_placeholder_end + - include: string_placeholder_width + - include: raw_string_placeholder_format + - match: '[^"}]+' + scope: invalid.illegal.unexpected-character-in-placeholder.cs + extended_verbatim_string_placeholders: - match: '(\{)(\d+)' captures: @@ -2159,10 +2191,10 @@ contexts: 1: punctuation.definition.placeholder.end.cs 2: invalid.illegal.unescaped-placeholder.cs pop: true - - match: (?=[}"]) + - match: (?=") pop: true - string_replacement_width: + string_interpolation_width: - match: '\s*(?:(,)\s*(?:((-?)\d+)|({{name}}))\s*)?' scope: meta.format-spec.cs captures: @@ -2201,6 +2233,21 @@ contexts: - match: '\{' scope: invalid.illegal.unescaped-placeholder.cs + raw_string_placeholder_format: + - match: ':' + scope: punctuation.separator.cs + push: inside_raw_string_placeholder_format + + inside_raw_string_placeholder_format: + - meta_scope: meta.format-spec.cs + - meta_content_scope: constant.other.format-spec.cs + - match: (?=[}"]) + pop: true + - match: \\ + scope: invalid.illegal.lone-escape.cs + - match: \{ + scope: invalid.illegal.unescaped-placeholder.cs + verbatim_string_placeholder_format: - match: ':(?="(?!"))' scope: invalid.illegal.unclosed-string-placeholder.cs diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index efd2ec0fe1..87f650b9bc 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -13,7 +13,24 @@ Some have "quoted text" in them. /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple - punctuation Escapes like \0 \a \f \n \t "" are literals. -///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant.character - invalid +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + Literal placeholders {0,20:F3}}! +/// ^^^^^^^^^ constant.other.placeholder.cs +/// ^ punctuation.definition.placeholder.begin.cs +/// ^ meta.number.integer.decimal.cs constant.numeric.value.cs +/// ^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ meta.number.integer.decimal.cs constant.numeric.value.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ punctuation.definition.placeholder.end.cs +/// ^ invalid.illegal.unescaped-placeholder.cs + + GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! +/// ^^ constant.character.escape.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation +/// ^^ constant.character.escape.cs """; /// ^^^ string.quoted.triple punctuation.definition.string.end @@ -23,33 +40,92 @@ embedded quote characters in a sequence. That's why it starts and ends with five double quotes. Escapes like \0 \a \f \n \t "" are literals. -///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant.character - invalid +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + Literal placeholders {0,20:F3}}! +/// ^^^^^^^^^ constant.other.placeholder.cs +/// ^ punctuation.definition.placeholder.begin.cs +/// ^ meta.number.integer.decimal.cs constant.numeric.value.cs +/// ^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ meta.number.integer.decimal.cs constant.numeric.value.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ punctuation.definition.placeholder.end.cs +/// ^ invalid.illegal.unescaped-placeholder.cs + + GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! +/// ^^ constant.character.escape.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation +/// ^^ constant.character.escape.cs """"" // - no semi-colon on the line above -var location = $$""" -/// <- storage.type.variable -/// ^^^^^^^^ variable.other -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin - You are at {{{Longitude}} \t {{Latitude}}} -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^ - constant -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^^ - constant -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^^ meta.string.interpolated string.quoted.triple constant.character.escape -/// ^ - constant - """; - var location = $""" /// ^^^^^ meta.string.interpolated string.quoted.triple /// ^^^^ punctuation.definition.string.begin /// ^ - invalid - You are at {{{Longitude}} \t {{Latitude}}} -///^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^^^^^^^^^^ meta.string.interpolated meta.interpolation - string -/// ^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple -/// ^^ - constant.character + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {Longitude}} \t {{Latitude}}} +///^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ variable.other.cs +/// ^ punctuation.section.interpolation.end.cs +/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^^ - constant.character +/// ^^ invalid.illegal.unescaped-placeholder.cs +/// ^^^ invalid.illegal.unescaped-placeholder.cs + + GMT is {DateTime.Now,width:yyyyMMdd\THHmmss\Z}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^ punctuation.section.interpolation.end.cs + + "{Incomplete:F"} "{Incomplete:F\"} {Brace:{}} +///^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs +/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs +/// ^ punctuation.section.interpolation.end.cs +/// ^ invalid.illegal.unescaped-placeholder.cs """; /// <- meta.string.interpolated string.quoted.triple ///^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.end @@ -60,18 +136,41 @@ You are at {{{Longitude}} \t {{Latitude}}} /// ^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs /// ^^^ punctuation.definition.string.begin.cs /// ^^ constant.character.escape.cs - You are at {{{Longitude}} \t {{Latitude}}} -///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs -/// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs -/// ^^ constant.character.escape.cs -/// ^ punctuation.section.interpolation.begin.cs -/// ^^^^^^^^^ variable.other.cs -/// ^ punctuation.section.interpolation.end.cs -/// ^^^^^ - constant + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation /// ^^ constant.character.escape.cs -/// ^^ constant.character.escape.cs -/// ^ - constant +/// ^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{Longitude}} \t {{Latitude}}} +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^ constant.character.escape.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ variable.other.cs +/// ^ punctuation.section.interpolation.end.cs +/// ^^^^^ - constant +/// ^^ constant.character.escape.cs +/// ^^ constant.character.escape.cs +/// ^ - constant + + GMT is {DateTime.Now,width:yyyyMMdd\THHmmss\Z}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs +/// ^^ constant.character.escape.cs +/// ^^ constant.character.escape.cs +/// ^ punctuation.section.interpolation.end.cs """; /// <- meta.string.interpolated.cs string.quoted.double.raw.cs ///^^^ meta.string.interpolated.cs string.quoted.double.raw.cs @@ -79,6 +178,89 @@ You are at {{{Longitude}} \t {{Latitude}}} /// ^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs +var location = $$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{Longitude}}} \t {Latitude}} } +///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^ - constant - invalid - punctuation +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ variable.other.cs +/// ^^ punctuation.section.interpolation.end.cs +/// ^^^^^^ - constant - invalid - punctuation +/// ^^ invalid.illegal.unescaped-placeholder.cs +/// ^ - constant - invalid - punctuation + + GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + +var location = @$$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^ invalid.illegal.reserved-char.cs +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{Longitude}}} \t {Latitude}} } +///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^ - constant - invalid - punctuation +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ variable.other.cs +/// ^^ punctuation.section.interpolation.end.cs +/// ^^^^^^ - constant - invalid - punctuation +/// ^^ invalid.illegal.unescaped-placeholder.cs +/// ^ - constant - invalid - punctuation + + GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y)} from the origin"""; /// ^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated @@ -145,7 +327,7 @@ The following example shows how newlines can improve the readability of an expre string s2 = @$$"""He said, ""This is the last \u0063hance\x0021"""; /// ^ invalid.illegal.reserved-char.cs -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple - constant /// ^^^^^ punctuation.definition.string.begin /// ^^ - constant.character /// ^^^^^^^^^^^^^^^^^ - constant diff --git a/C#/tests/syntax_test_GeneralStructure.cs b/C#/tests/syntax_test_GeneralStructure.cs index cccaa781e6..791d4b18c7 100644 --- a/C#/tests/syntax_test_GeneralStructure.cs +++ b/C#/tests/syntax_test_GeneralStructure.cs @@ -1254,6 +1254,7 @@ void TestMe () { /// ^ invalid.illegal.unclosed-string-placeholder /// ^ punctuation.definition.string.end /// ^ string - invalid - constant.other - punctuation +/// ^ string - invalid - constant.other - punctuation formatted = string.Format("{0", myInt); /// ^^ constant.other.placeholder /// ^ invalid.illegal.unclosed-string-placeholder @@ -1262,6 +1263,8 @@ void TestMe () { /// ^^ constant.character.escape /// ^^^ invalid.illegal.unclosed-string-placeholder /// ^ punctuation.definition.string.end +/// ^ string - invalid - constant.other - punctuation + formatted = string.Format("{1:\",{{}} {}", myInt, "}"); /// ^^^^^^^^^^^^^ constant.other.placeholder /// ^ punctuation.definition.placeholder.begin @@ -1269,6 +1272,7 @@ void TestMe () { /// ^^^^ constant.character.escape /// ^ invalid.illegal.unescaped-placeholder /// ^ punctuation.definition.placeholder.end +/// ^ string - invalid - constant.other - punctuation formatted = string.Format(@"{0:00.00000{{}}test""} me", 5); /// ^^^^^^^^^^^^^^^^^^^^^^ constant.other.placeholder - invalid /// ^^^^ constant.character.escape From 7d4fdd0c838855b94300c254597db641b79aab5e Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 16:24:27 +0100 Subject: [PATCH 06/14] [C#] Add support for `$$$` strings. --- C#/C#.sublime-syntax | 60 ++++++++++++- C#/tests/syntax_test_C#11.cs | 166 +++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+), 2 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 3ec4140648..c2ce350747 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1944,12 +1944,18 @@ contexts: scope: punctuation.definition.string.begin.cs push: inside_string # interpolated raw format strings - - match: '\$("""+)' + - match: '\${1}("""+)' scope: punctuation.definition.string.begin.cs push: inside_raw_format_string_1 - - match: '\$\$("""+)' + - match: '\${2}("""+)' scope: punctuation.definition.string.begin.cs push: inside_raw_format_string_2 + - match: '\${3}("""+)' + scope: punctuation.definition.string.begin.cs + push: inside_raw_format_string_3 + - match: '\${4}("""+)' + scope: punctuation.definition.string.begin.cs + push: inside_raw_format_string_4 # interpolated quoted format strings - match: '\$"' scope: punctuation.definition.string.begin.cs @@ -2086,6 +2092,56 @@ contexts: - include: raw_string_placeholder_format - include: line_of_code_in + inside_raw_format_string_3: + - meta_include_prototype: false + - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - match: \1 + scope: punctuation.definition.string.end.cs + pop: true + - match: \{{3}(?!\{) + scope: punctuation.section.interpolation.begin.cs + push: inside_raw_format_string_interpolation_3 + - match: \}{3,} + scope: invalid.illegal.unexpected-token.cs + + inside_raw_format_string_interpolation_3: + - clear_scopes: 1 + - meta_scope: meta.interpolation.cs + - meta_content_scope: source.cs + - match: \}{3} + scope: punctuation.section.interpolation.end.cs + pop: true + - match: (?=") + pop: true + - include: string_interpolation_width + - include: raw_string_placeholder_format + - include: line_of_code_in + + inside_raw_format_string_4: + - meta_include_prototype: false + - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - match: \1 + scope: punctuation.definition.string.end.cs + pop: true + - match: \{{4}(?!\{) + scope: punctuation.section.interpolation.begin.cs + push: inside_raw_format_string_interpolation_4 + - match: \}{4,} + scope: invalid.illegal.unexpected-token.cs + + inside_raw_format_string_interpolation_4: + - clear_scopes: 1 + - meta_scope: meta.interpolation.cs + - meta_content_scope: source.cs + - match: \}{4} + scope: punctuation.section.interpolation.end.cs + pop: true + - match: (?=") + pop: true + - include: string_interpolation_width + - include: raw_string_placeholder_format + - include: line_of_code_in + inside_verbatim_format_string: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 87f650b9bc..462b2b0db1 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -261,6 +261,172 @@ You are at {{{Longitude}}} \t {Latitude}} } ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs +var location = $$$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ - constant - invalid - punctuation +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ source.cs variable.other.cs +/// ^^^ punctuation.section.interpolation.end.cs +/// ^^^^^^^^ - constant - invalid - punctuation +/// ^^^ invalid.illegal.unexpected-token.cs +/// ^^ - constant - invalid - punctuation + + GMT is {{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + +var location = @$$$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^ invalid.illegal.reserved-char.cs +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ - constant - invalid - punctuation +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ source.cs variable.other.cs +/// ^^^ punctuation.section.interpolation.end.cs +/// ^^^^^^^^ - constant - invalid - punctuation +/// ^^^ invalid.illegal.unexpected-token.cs +/// ^^ - constant - invalid - punctuation + + GMT is {{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + +var location = $$$$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} +///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^ - constant - invalid - punctuation +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ source.cs variable.other.cs +/// ^^^^ punctuation.section.interpolation.end.cs +/// ^^^^^^^^^^ - constant - invalid - punctuation +/// ^^^^ invalid.illegal.unexpected-token.cs +/// ^^^ - constant - invalid - punctuation + + GMT is {{{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + +var location = @$$$$""" +/// <- storage.type.variable +/// ^^^^^^^^ variable.other +/// ^ invalid.illegal.reserved-char.cs +/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin + + Escapes like \0 \a \f \n \t "" are literals. +///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation + + You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} +///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^ - constant - invalid - punctuation +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^ source.cs variable.other.cs +/// ^^^^ punctuation.section.interpolation.end.cs +/// ^^^^^^^^^^ - constant - invalid - punctuation +/// ^^^^ invalid.illegal.unexpected-token.cs +/// ^^^ - constant - invalid - punctuation + + GMT is {{{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}}! +///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^ variable.other.cs +/// ^ punctuation.accessor.dot.cs +/// ^^^ variable.other.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^^^^ variable.other.cs +/// ^ punctuation.separator.cs +/// ^^^^^^^^^^^^^^^^^^ constant.other.format-spec.cs - constant.character +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^^ punctuation.section.interpolation.end.cs + """; +///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ punctuation.definition.string.end.cs +/// ^ punctuation.terminator.statement.cs + var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y)} from the origin"""; /// ^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated From af927d8603711617bde11b1746981950382c4408 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sat, 28 Mar 2026 21:17:48 +0100 Subject: [PATCH 07/14] [C#] Reorganize contexts 1. sort string contexts by quoted, verbatim and raw strings 2. move extended placeholders contexts to to related string content contexts as interpolation contexts are organized this way. 3. include `string_placeholders` and `string_placeholder_escapes` separately. --- C#/C#.sublime-syntax | 382 ++++++++++++++++++++++--------------------- 1 file changed, 198 insertions(+), 184 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index c2ce350747..0ce0beb274 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -1929,6 +1929,8 @@ contexts: 2: constant.numeric.suffix.cs - include: strings +###[ STRINGS ]################################################################# + strings: # literal raw strings - match: '(""""+)' @@ -1973,6 +1975,8 @@ contexts: - inside_verbatim_format_string - inside_verbatim_format_string_syntax +###[ QUOTED STRINGS ]########################################################## + inside_string: - meta_include_prototype: false - meta_scope: meta.string.cs string.quoted.double.cs @@ -1980,12 +1984,25 @@ contexts: scope: punctuation.definition.string.end.cs pop: true - include: string_escapes + - include: string_placeholder_escapes - include: string_placeholders - - include: extended_string_placeholders + - match: (\{)(\d+) + captures: + 1: punctuation.definition.placeholder.begin.cs + 2: meta.number.integer.decimal.cs constant.numeric.value.cs + push: inside_extended_string_placeholder - match: $\n? scope: invalid.illegal.unclosed-string.cs pop: true + inside_extended_string_placeholder: + - meta_scope: constant.other.placeholder.cs + - include: string_placeholder_end + - include: string_placeholder_width + - include: string_placeholder_format + - match: '[^"}]+' + scope: invalid.illegal.unexpected-character-in-placeholder.cs + inside_format_string: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.double.cs @@ -2014,14 +2031,138 @@ contexts: - include: string_placeholder_format - include: line_of_code_in - inside_raw_string: + string_placeholder_format: + - match: ':(?=")' + scope: invalid.illegal.unclosed-string-placeholder.cs + pop: true + - match: ':' + scope: punctuation.separator.cs + push: inside_string_placeholder_format + + inside_string_placeholder_format: + - meta_scope: meta.format-spec.cs + - meta_content_scope: constant.other.format-spec.cs + - include: string_escapes + - include: string_placeholder_escapes + - match: (?=\}) + pop: true + - match: (?:[^}"\\](?:\\.)*)+(?=") + scope: invalid.illegal.unclosed-string-placeholder.cs + pop: true + - match: \{ + scope: invalid.illegal.unescaped-placeholder.cs + +###[ VERBATIM STRINGS ]######################################################## + + inside_verbatim_string: - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.triple.cs - - match: \1 + - meta_scope: meta.string.cs string.quoted.double.raw.cs + - include: verbatim_string_escapes + - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_placeholder_escapes - include: string_placeholders - - include: extended_raw_string_placeholders + - include: extended_verbatim_string_placeholders + + inside_verbatim_string_syntax: + - meta_include_prototype: false + - match: (?={{sql_indicator}}) + set: scope:source.sql + with_prototype: + - include: verbatim_string_escapes + - match: (?=") + pop: true + - include: string_placeholder_escapes + - include: string_placeholders + - include: extended_verbatim_string_placeholders + - match: (?=\S) + pop: true + + extended_verbatim_string_placeholders: + - match: (\{)(\d+) + captures: + 1: punctuation.definition.placeholder.begin.cs + 2: meta.number.integer.decimal.cs constant.numeric.value.cs + push: inside_extended_verbatim_string_placeholder + + inside_extended_verbatim_string_placeholder: + - meta_scope: constant.other.placeholder.cs + - include: string_placeholder_end + - include: string_placeholder_width + - include: verbatim_string_placeholder_format + - match: '[^"}]+' + scope: invalid.illegal.unexpected-character-in-placeholder.cs + + inside_verbatim_format_string: + - meta_include_prototype: false + - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs + - include: verbatim_string_escapes + - match: '"' + scope: punctuation.definition.string.end.cs + pop: true + - include: string_placeholder_escapes + - include: verbatim_format_string_interpolations + + inside_verbatim_format_string_syntax: + - meta_include_prototype: false + - match: (?={{sql_indicator}}) + set: scope:source.sql + with_prototype: + - include: verbatim_string_escapes + - match: (?=") + pop: true + - include: string_placeholder_escapes + - include: verbatim_format_string_interpolations + - match: (?=\S) + pop: true + + verbatim_format_string_interpolations: + - match: \{ + scope: punctuation.section.interpolation.begin.cs + push: inside_verbatim_format_string_interpolation + + inside_verbatim_format_string_interpolation: + - clear_scopes: 1 + - meta_scope: meta.interpolation.cs + - meta_content_scope: source.cs + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true + - match: (?=") + pop: true + - include: string_interpolation_width + - include: verbatim_string_placeholder_format + - include: line_of_code_in + + verbatim_string_placeholder_format: + - match: ':(?="(?!"))' + scope: invalid.illegal.unclosed-string-placeholder.cs + pop: true + - match: ':' + scope: punctuation.separator.cs + push: inside_verbatim_string_placeholder_format + + inside_verbatim_string_placeholder_format: + - meta_scope: meta.format-spec.cs + - meta_content_scope: constant.other.format-spec.cs + - include: verbatim_string_escapes + - include: string_placeholder_escapes + - match: (?=\}) + pop: true + - match: \\(?:""|[^"]) + scope: constant.character.escape.cs + - match: (?:[^}"]|"")+(?="(?!")) + scope: invalid.illegal.unclosed-string-placeholder.cs + pop: true + - match: \{ + scope: invalid.illegal.unescaped-placeholder.cs + + verbatim_string_escapes: + - match: '""' + scope: constant.character.escape.cs + +###[ RAW STRINGS ]############################################################# inside_triple_quoted_raw_string: - meta_include_prototype: false @@ -2029,6 +2170,7 @@ contexts: - match: '"""' scope: punctuation.definition.string.end.cs pop: true + - include: string_placeholder_escapes - include: string_placeholders - include: extended_raw_string_placeholders @@ -2042,6 +2184,31 @@ contexts: - match: (?=\S) pop: true + inside_raw_string: + - meta_include_prototype: false + - meta_scope: meta.string.cs string.quoted.triple.cs + - match: \1 + scope: punctuation.definition.string.end.cs + pop: true + - include: string_placeholder_escapes + - include: string_placeholders + - include: extended_raw_string_placeholders + + extended_raw_string_placeholders: + - match: (\{)(\d+) + captures: + 1: punctuation.definition.placeholder.begin.cs + 2: meta.number.integer.decimal.cs constant.numeric.value.cs + push: inside_extended_raw_string_placeholder + + inside_extended_raw_string_placeholder: + - meta_scope: constant.other.placeholder.cs + - include: string_placeholder_end + - include: string_placeholder_width + - include: raw_string_placeholder_format + - match: '[^"}]+' + scope: invalid.illegal.unexpected-character-in-placeholder.cs + inside_raw_format_string_1: - meta_include_prototype: false - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs @@ -2142,107 +2309,44 @@ contexts: - include: raw_string_placeholder_format - include: line_of_code_in - inside_verbatim_format_string: - - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs - - include: verbatim_string_escapes - - match: '"' - scope: punctuation.definition.string.end.cs + raw_string_placeholder_format: + - match: ':' + scope: punctuation.separator.cs + push: inside_raw_string_placeholder_format + + inside_raw_string_placeholder_format: + - meta_scope: meta.format-spec.cs + - meta_content_scope: constant.other.format-spec.cs + - match: (?=[}"]) pop: true - - include: string_placeholder_escapes + - match: \\ + scope: invalid.illegal.lone-escape.cs - match: \{ - scope: punctuation.section.interpolation.begin.cs - push: inside_verbatim_format_string_interpolation + scope: invalid.illegal.unescaped-placeholder.cs - inside_verbatim_format_string_syntax: - - meta_include_prototype: false - - match: (?={{sql_indicator}}) - set: scope:source.sql - with_prototype: - - include: verbatim_string_escapes - - match: (?=") - pop: true - - include: string_placeholder_escapes - - match: \{ - scope: punctuation.section.interpolation.begin.cs - push: inside_verbatim_format_string_interpolation - - match: (?=\S) - pop: true +###[ STRING PROTOTYPES ]####################################################### - inside_verbatim_format_string_interpolation: - - clear_scopes: 1 - - meta_scope: meta.interpolation.cs - - meta_content_scope: source.cs - - match: \} - scope: punctuation.section.interpolation.end.cs - pop: true - - match: (?=") - pop: true - - include: string_interpolation_width - - include: verbatim_string_placeholder_format - - include: line_of_code_in + string_escapes: + - match: '{{escaped_char}}' + scope: constant.character.escape.cs + - match: \\ + scope: invalid.illegal.lone-escape.cs string_placeholder_escapes: - - match: '\{\{|\}\}' + - match: \{\{|\}\} scope: constant.character.escape.cs string_placeholders: - - include: string_placeholder_escapes - match: \{\h{8}-(?:\h{4}-){3}\h{12}\} scope: constant.other.guid.cs - - match: '(\{)(\d+)(?=")' + - match: (\{)(\d+)(?=") scope: constant.other.placeholder.cs captures: 1: punctuation.definition.placeholder.begin.cs 2: meta.number.integer.decimal.cs constant.numeric.value.cs invalid.illegal.unclosed-string-placeholder.cs - extended_string_placeholders: - - match: '(\{)(\d+)' - captures: - 1: punctuation.definition.placeholder.begin.cs - 2: meta.number.integer.decimal.cs constant.numeric.value.cs - push: inside_extended_string_placeholder - - inside_extended_string_placeholder: - - meta_scope: constant.other.placeholder.cs - - include: string_placeholder_end - - include: string_placeholder_width - - include: string_placeholder_format - - match: '[^"}]+' - scope: invalid.illegal.unexpected-character-in-placeholder.cs - - extended_raw_string_placeholders: - - match: '(\{)(\d+)' - captures: - 1: punctuation.definition.placeholder.begin.cs - 2: meta.number.integer.decimal.cs constant.numeric.value.cs - push: inside_extended_raw_string_placeholder - - inside_extended_raw_string_placeholder: - - meta_scope: constant.other.placeholder.cs - - include: string_placeholder_end - - include: string_placeholder_width - - include: raw_string_placeholder_format - - match: '[^"}]+' - scope: invalid.illegal.unexpected-character-in-placeholder.cs - - extended_verbatim_string_placeholders: - - match: '(\{)(\d+)' - captures: - 1: punctuation.definition.placeholder.begin.cs - 2: meta.number.integer.decimal.cs constant.numeric.value.cs - push: inside_extended_verbatim_string_placeholder - - inside_extended_verbatim_string_placeholder: - - meta_scope: constant.other.placeholder.cs - - include: string_placeholder_end - - include: string_placeholder_width - - include: verbatim_string_placeholder_format - - match: '[^"}]+' - scope: invalid.illegal.unexpected-character-in-placeholder.cs - string_placeholder_end: - - match: '(\})(\}(?!\}))?' + - match: (\})(\}(?!\}))? captures: 1: punctuation.definition.placeholder.end.cs 2: invalid.illegal.unescaped-placeholder.cs @@ -2250,8 +2354,8 @@ contexts: - match: (?=") pop: true - string_interpolation_width: - - match: '\s*(?:(,)\s*(?:((-?)\d+)|({{name}}))\s*)?' + string_placeholder_width: + - match: \s*(?:(,)\s*((-?)\d+)\s*)? scope: meta.format-spec.cs captures: 1: punctuation.separator.cs @@ -2259,8 +2363,8 @@ contexts: 3: keyword.operator.arithmetic.cs 4: variable.other.cs - string_placeholder_width: - - match: '\s*(?:(,)\s*((-?)\d+)\s*)?' + string_interpolation_width: + - match: \s*(?:(,)\s*(?:((-?)\d+)|({{name}}))\s*)? scope: meta.format-spec.cs captures: 1: punctuation.separator.cs @@ -2268,97 +2372,7 @@ contexts: 3: keyword.operator.arithmetic.cs 4: variable.other.cs - string_placeholder_format: - - match: ':(?=")' - scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true - - match: ':' - scope: punctuation.separator.cs - push: inside_string_placeholder_format - - inside_string_placeholder_format: - - meta_scope: meta.format-spec.cs - - meta_content_scope: constant.other.format-spec.cs - - include: string_placeholder_escapes - - include: string_escapes - - match: '(?=\})' - pop: true - - match: '(?:[^}"\\](?:\\.)*)+(?=")' - scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true - - match: '\{' - scope: invalid.illegal.unescaped-placeholder.cs - - raw_string_placeholder_format: - - match: ':' - scope: punctuation.separator.cs - push: inside_raw_string_placeholder_format - - inside_raw_string_placeholder_format: - - meta_scope: meta.format-spec.cs - - meta_content_scope: constant.other.format-spec.cs - - match: (?=[}"]) - pop: true - - match: \\ - scope: invalid.illegal.lone-escape.cs - - match: \{ - scope: invalid.illegal.unescaped-placeholder.cs - - verbatim_string_placeholder_format: - - match: ':(?="(?!"))' - scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true - - match: ':' - scope: punctuation.separator.cs - push: inside_verbatim_string_placeholder_format - - inside_verbatim_string_placeholder_format: - - meta_scope: meta.format-spec.cs - - meta_content_scope: constant.other.format-spec.cs - - include: string_placeholder_escapes - - include: verbatim_string_escapes - - match: (?=\}) - pop: true - - match: \\(?:""|[^"]) - scope: constant.character.escape.cs - - match: (?:[^}"]|"")+(?="(?!")) - scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true - - match: \{ - scope: invalid.illegal.unescaped-placeholder.cs - - inside_verbatim_string: - - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.double.raw.cs - - include: verbatim_string_escapes - - match: '"' - scope: punctuation.definition.string.end.cs - pop: true - - include: string_placeholders - - include: extended_verbatim_string_placeholders - - inside_verbatim_string_syntax: - - meta_include_prototype: false - - match: (?={{sql_indicator}}) - set: scope:source.sql - with_prototype: - - include: verbatim_string_escapes - - match: (?=") - pop: true - - include: string_placeholders - - include: extended_verbatim_string_placeholders - - match: (?=\S) - pop: true - - string_escapes: - - match: '{{escaped_char}}' - scope: constant.character.escape.cs - - match: \\ - scope: invalid.illegal.lone-escape.cs - - verbatim_string_escapes: - - match: '""' - scope: constant.character.escape.cs +###[ INITIALIZERS ]############################################################ initializer_constructor: - meta_content_scope: meta.instance.cs meta.braces.cs From e649829c7f687789ede96e847e2ea9568ed7818c Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 12:41:45 +0200 Subject: [PATCH 08/14] [C#] Improve interpolation termination This commit adds and tweaks interpolation bailouts in double quoted strings. --- C#/C#.sublime-syntax | 29 +++++++-------- C#/tests/syntax_test_GeneralStructure.cs | 45 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 17 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 0ce0beb274..60412b0903 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2022,11 +2022,7 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: \} - scope: punctuation.section.interpolation.end.cs - pop: true - - match: (?=") - pop: true + - include: string_interpolation_end - include: string_interpolation_width - include: string_placeholder_format - include: line_of_code_in @@ -2044,7 +2040,7 @@ contexts: - meta_content_scope: constant.other.format-spec.cs - include: string_escapes - include: string_placeholder_escapes - - match: (?=\}) + - match: (?=[}"]) pop: true - match: (?:[^}"\\](?:\\.)*)+(?=") scope: invalid.illegal.unclosed-string-placeholder.cs @@ -2126,11 +2122,7 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: \} - scope: punctuation.section.interpolation.end.cs - pop: true - - match: (?=") - pop: true + - include: string_interpolation_end - include: string_interpolation_width - include: verbatim_string_placeholder_format - include: line_of_code_in @@ -2148,7 +2140,7 @@ contexts: - meta_content_scope: constant.other.format-spec.cs - include: verbatim_string_escapes - include: string_placeholder_escapes - - match: (?=\}) + - match: (?=[}"]) pop: true - match: \\(?:""|[^"]) scope: constant.character.escape.cs @@ -2225,11 +2217,7 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - match: \} - scope: punctuation.section.interpolation.end.cs - pop: true - - match: (?=") - pop: true + - include: string_interpolation_end - include: string_interpolation_width - include: raw_string_placeholder_format - include: line_of_code_in @@ -2363,6 +2351,13 @@ contexts: 3: keyword.operator.arithmetic.cs 4: variable.other.cs + string_interpolation_end: + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true + - match: (?=") + pop: true + string_interpolation_width: - match: \s*(?:(,)\s*(?:((-?)\d+)|({{name}}))\s*)? scope: meta.format-spec.cs diff --git a/C#/tests/syntax_test_GeneralStructure.cs b/C#/tests/syntax_test_GeneralStructure.cs index 791d4b18c7..6e6b787d2c 100644 --- a/C#/tests/syntax_test_GeneralStructure.cs +++ b/C#/tests/syntax_test_GeneralStructure.cs @@ -1303,6 +1303,51 @@ void TestMe () { /// ^ invalid.illegal.lone-escape /// ^ punctuation.section.interpolation.end /// ^ punctuation.definition.string.end + Console.WriteLine(@$"GMT is {DateTime.Now"); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine(@$"GMT is {DateTime.Now"""); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^^ meta.string.interpolated.cs string.quoted.double.raw.cs constant.character.escape.cs +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine(@$"GMT is {DateTime.Now:"); +/// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ invalid.illegal.unclosed-string-placeholder.cs +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine(@$"GMT is {DateTime.Now:"""); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine(@$"GMT is {DateTime.Now:yyyyMMdd\THHmmss\Z"); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation meta.format-spec +/// ^ meta.string.interpolated - meta.interpolation - meta.format-spec +/// ^ punctuation.separator - constant.other.format-spec +/// ^^^^^^^^^^^^^^^^^^ invalid.illegal.unclosed-string-placeholder.cs +/// ^ punctuation.definition.string.end + Console.WriteLine($"GMT is {DateTime.Now"); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine($"GMT is {DateTime.Now"""); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec +/// ^^ meta.string.cs string.quoted.double.cs punctuation + Console.WriteLine($"GMT is {DateTime.Now:"); +/// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ invalid.illegal.unclosed-string-placeholder.cs +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec + Console.WriteLine($"GMT is {DateTime.Now:"""); +/// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^ invalid.illegal.unclosed-string-placeholder.cs +/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec +/// ^^ meta.string.cs string.quoted.double.cs punctuation + Console.WriteLine($"GMT is {DateTime.Now:yyyyMMdd\THHmmss\Z"); +/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation meta.format-spec +/// ^ meta.string.interpolated - meta.interpolation - meta.format-spec +/// ^ punctuation.separator - constant.other.format-spec +/// ^^^^^^^^^^^^^^^^^^ invalid.illegal.unclosed-string-placeholder.cs +/// ^ punctuation.definition.string.end Console.WriteLine($@"GMT is {DateTime.Now:yyyyMMdd\T\""\x1043HHmmss\Z}"); /// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation meta.format-spec From 70d8ed17666d83d8f73909f927208c8220f98b65 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 14:06:47 +0200 Subject: [PATCH 09/14] [C#] Additional invalid closing braces --- C#/C#.sublime-syntax | 4 ++++ C#/tests/syntax_test_GeneralStructure.cs | 21 ++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 60412b0903..5465deeb9e 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2014,6 +2014,8 @@ contexts: - match: \{ scope: punctuation.section.interpolation.begin.cs push: inside_format_string_interpolation + - match: \} + scope: invalid.illegal.unescaped-placeholder.cs - match: $\n? scope: invalid.illegal.unclosed-string.cs pop: true @@ -2117,6 +2119,8 @@ contexts: - match: \{ scope: punctuation.section.interpolation.begin.cs push: inside_verbatim_format_string_interpolation + - match: \} + scope: invalid.illegal.unescaped-placeholder.cs inside_verbatim_format_string_interpolation: - clear_scopes: 1 diff --git a/C#/tests/syntax_test_GeneralStructure.cs b/C#/tests/syntax_test_GeneralStructure.cs index 6e6b787d2c..35d3081ac1 100644 --- a/C#/tests/syntax_test_GeneralStructure.cs +++ b/C#/tests/syntax_test_GeneralStructure.cs @@ -1264,7 +1264,6 @@ void TestMe () { /// ^^^ invalid.illegal.unclosed-string-placeholder /// ^ punctuation.definition.string.end /// ^ string - invalid - constant.other - punctuation - formatted = string.Format("{1:\",{{}} {}", myInt, "}"); /// ^^^^^^^^^^^^^ constant.other.placeholder /// ^ punctuation.definition.placeholder.begin @@ -1273,6 +1272,7 @@ void TestMe () { /// ^ invalid.illegal.unescaped-placeholder /// ^ punctuation.definition.placeholder.end /// ^ string - invalid - constant.other - punctuation + formatted = string.Format(@"{0:00.00000{{}}test""} me", 5); /// ^^^^^^^^^^^^^^^^^^^^^^ constant.other.placeholder - invalid /// ^^^^ constant.character.escape @@ -1281,10 +1281,21 @@ void TestMe () { /// ^^^^^ variable.other - variable.parameter /// ^^^^^ variable.other - variable.parameter /// ^^ keyword.operator - keyword.operator.assignment + + formatted = string.Format(@"GMT is {{ } }}"); +/// ^^ constant.character.escape.cs +/// ^ - invalid +/// ^^ constant.character.escape.cs + formatted = string.Format("GMT is {{ } }}"); +/// ^^ constant.character.escape.cs +/// ^ - invalid +/// ^^ constant.character.escape.cs + formatted = string.Format(@"GMT is {0:yyyyMMdd\THHmmss\Z}", DateTime.Now.ToUniversalTime()); /// ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.raw constant.other.placeholder formatted = string.Format("GMT is {0:yyyyMMdd\\THHmmss\\Z}", DateTime.Now.ToUniversalTime()); /// ^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double constant.other.placeholder + Console.WriteLine($@"GMT is {DateTime.Now:yyyyMMdd\THHmmss\Z}"); /// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation meta.format-spec @@ -1303,6 +1314,10 @@ void TestMe () { /// ^ invalid.illegal.lone-escape /// ^ punctuation.section.interpolation.end /// ^ punctuation.definition.string.end + Console.WriteLine(@$"GMT is {{ } }}"); +/// ^^ constant.character.escape.cs +/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^^ constant.character.escape.cs Console.WriteLine(@$"GMT is {DateTime.Now"); /// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec @@ -1325,6 +1340,10 @@ void TestMe () { /// ^ punctuation.separator - constant.other.format-spec /// ^^^^^^^^^^^^^^^^^^ invalid.illegal.unclosed-string-placeholder.cs /// ^ punctuation.definition.string.end + Console.WriteLine($"GMT is {{ } }}"); +/// ^^ constant.character.escape.cs +/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^^ constant.character.escape.cs Console.WriteLine($"GMT is {DateTime.Now"); /// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec From 96c5389f1945058dee37f800f5778ea1a6a023f6 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 14:22:06 +0200 Subject: [PATCH 10/14] [C#] Change verbatim string scopes This commit changes scope to avoid confusion between verbatim and raw strings. --- C#/C#.sublime-syntax | 4 ++-- C#/tests/syntax_test_C#11.cs | 16 ++++++++-------- C#/tests/syntax_test_GeneralStructure.cs | 4 ++-- C#/tests/syntax_test_Strings.cs | 16 ++++++++-------- C#/tests/syntax_test_c#.cs | 6 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 5465deeb9e..9f0ec08c79 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2054,7 +2054,7 @@ contexts: inside_verbatim_string: - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.double.raw.cs + - meta_scope: meta.string.cs string.quoted.double.verbatim.cs - include: verbatim_string_escapes - match: '"' scope: punctuation.definition.string.end.cs @@ -2094,7 +2094,7 @@ contexts: inside_verbatim_format_string: - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.double.raw.cs + - meta_scope: meta.string.interpolated.cs string.quoted.double.verbatim.cs - include: verbatim_string_escapes - match: '"' scope: punctuation.definition.string.end.cs diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 462b2b0db1..597fec3e07 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -133,7 +133,7 @@ You are at {Longitude}} \t {{Latitude}}} // Note: Verbatim strings may look like raw strings when starting with escaped double-quotes var location = @$""" -/// ^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs /// ^^^ punctuation.definition.string.begin.cs /// ^^ constant.character.escape.cs @@ -143,9 +143,9 @@ Escapes like \0 \a \f \n \t "" are literals. /// ^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{Longitude}} \t {{Latitude}}} -///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs /// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs /// ^^ constant.character.escape.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ variable.other.cs @@ -156,9 +156,9 @@ You are at {{{Longitude}} \t {{Latitude}}} /// ^ - constant GMT is {DateTime.Now,width:yyyyMMdd\THHmmss\Z}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -172,8 +172,8 @@ You are at {{{Longitude}} \t {{Latitude}}} /// ^^ constant.character.escape.cs /// ^ punctuation.section.interpolation.end.cs """; -/// <- meta.string.interpolated.cs string.quoted.double.raw.cs -///^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// <- meta.string.interpolated.cs string.quoted.double.verbatim.cs +///^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs ///^^ constant.character.escape.cs /// ^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs @@ -486,7 +486,7 @@ The following example shows how newlines can improve the readability of an expre // Horace is 34 years old. string s2 = @$"He said, ""This is the last \u0063hance\x0021"""; -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.double.raw +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.double.verbatim /// ^^^ punctuation.definition.string.begin /// ^^ constant.character.escape /// ^^^^^^^^^^^^^^^^^ - constant diff --git a/C#/tests/syntax_test_GeneralStructure.cs b/C#/tests/syntax_test_GeneralStructure.cs index 35d3081ac1..49889fbab3 100644 --- a/C#/tests/syntax_test_GeneralStructure.cs +++ b/C#/tests/syntax_test_GeneralStructure.cs @@ -1292,7 +1292,7 @@ void TestMe () { /// ^^ constant.character.escape.cs formatted = string.Format(@"GMT is {0:yyyyMMdd\THHmmss\Z}", DateTime.Now.ToUniversalTime()); -/// ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.raw constant.other.placeholder +/// ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.verbatim constant.other.placeholder formatted = string.Format("GMT is {0:yyyyMMdd\\THHmmss\\Z}", DateTime.Now.ToUniversalTime()); /// ^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double constant.other.placeholder @@ -1323,7 +1323,7 @@ void TestMe () { /// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec Console.WriteLine(@$"GMT is {DateTime.Now"""); /// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec -/// ^^ meta.string.interpolated.cs string.quoted.double.raw.cs constant.character.escape.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs constant.character.escape.cs /// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec Console.WriteLine(@$"GMT is {DateTime.Now:"); /// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec diff --git a/C#/tests/syntax_test_Strings.cs b/C#/tests/syntax_test_Strings.cs index eba8aea5ca..c491aea3e3 100644 --- a/C#/tests/syntax_test_Strings.cs +++ b/C#/tests/syntax_test_Strings.cs @@ -47,20 +47,20 @@ var interpolated_yes = $"foo {bar} foo"; /// ^^^^^^^^^^^^^^^^ meta.string.interpolated.cs var verbatim_singleline = @"foo"; -/// ^^^^^^ meta.string.cs string.quoted.double.raw.cs - meta.string.interpolated +/// ^^^^^^ meta.string.cs string.quoted.double.verbatim.cs - meta.string.interpolated var verbatim_singleline_interpolated_none = $@"foo bar"; -/// ^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs var verbatim_singleline_interpolated_yes = $@"foo {bar} foo"; -/// ^^^^^^^ string.quoted.double.raw.cs +/// ^^^^^^^ string.quoted.double.verbatim.cs /// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs var verbatim_multiline = @"foo bar -/// ^^^^^^^^^^ meta.string.cs string.quoted.double.raw.cs - meta.string.interpolated +/// ^^^^^^^^^^ meta.string.cs string.quoted.double.verbatim.cs - meta.string.interpolated baz"; var verbatim_multiline_interpolated_none = $@"foo bar -/// ^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs baz"; var verbatim_multiline_interpolated_yes = $@"foo {bar} -/// ^^^^^^ string.quoted.double.raw.cs +/// ^^^^^^ string.quoted.double.verbatim.cs /// ^^^^^^^^^^^^ meta.string.interpolated.cs baz"; @@ -68,7 +68,7 @@ SELECT * FROM foo WHERE SQLi='{0}'"; -///^^^^^^^^^^^^^^^^^^^^ meta.string.cs string.quoted.double.raw.cs - meta.string.interpolated +///^^^^^^^^^^^^^^^^^^^^ meta.string.cs string.quoted.double.verbatim.cs - meta.string.interpolated ///^^^^^^^^^^^^^^^^^^^ source.sql /// ^^^^^ keyword.other.dml.sql /// ^^^^ meta.column-name.sql @@ -87,7 +87,7 @@ FROM foo SELECT * FROM foo WHERE SQLi='{bar}'"; -///^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.raw.cs +///^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs ///^^^^^^^^^^^^^^^^^^^^^ source.sql /// ^^^^^ keyword.other.dml.sql /// ^^^^ meta.column-name.sql diff --git a/C#/tests/syntax_test_c#.cs b/C#/tests/syntax_test_c#.cs index 02f5af215f..91edb581f8 100644 --- a/C#/tests/syntax_test_c#.cs +++ b/C#/tests/syntax_test_c#.cs @@ -33,10 +33,10 @@ void Run([Usage("help text")] int x, int y) } string verbatim = @"This is a test "" of a verbatim string literal - C:\User"; -// ^^ string.quoted.double.raw punctuation.definition.string.begin +// ^^ string.quoted.double.verbatim punctuation.definition.string.begin // ^^ constant.character.escape -// ^ string.quoted.double.raw - constant -// ^ string.quoted.double.raw punctuation.definition.string.end +// ^ string.quoted.double.verbatim - constant +// ^ string.quoted.double.verbatim punctuation.definition.string.end class A { From c2bf0e8a8d89d4a67505f888bc3d1cd3a33c9c17 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 14:26:01 +0200 Subject: [PATCH 11/14] [C#] Change raw string scopes This commit scopes raw strings `string.quoted.block`, because... 1. they may be enclosed by any number of double quotes, which renders `.triple` scope name a bit inaccurate. 2. Python also scopes multi-line strings this way. --- C#/C#.sublime-syntax | 12 ++-- C#/tests/syntax_test_C#11.cs | 112 ++++++++++++++++---------------- C#/tests/syntax_test_Strings.cs | 6 +- 3 files changed, 65 insertions(+), 65 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 9f0ec08c79..69766774ba 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2162,7 +2162,7 @@ contexts: inside_triple_quoted_raw_string: - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.triple.cs + - meta_scope: meta.string.cs string.quoted.double.block.cs - match: '"""' scope: punctuation.definition.string.end.cs pop: true @@ -2182,7 +2182,7 @@ contexts: inside_raw_string: - meta_include_prototype: false - - meta_scope: meta.string.cs string.quoted.triple.cs + - meta_scope: meta.string.cs string.quoted.double.block.cs - match: \1 scope: punctuation.definition.string.end.cs pop: true @@ -2207,7 +2207,7 @@ contexts: inside_raw_format_string_1: - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - meta_scope: meta.string.interpolated.cs string.quoted.double.block.cs - match: \1 scope: punctuation.definition.string.end.cs pop: true @@ -2228,7 +2228,7 @@ contexts: inside_raw_format_string_2: - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - meta_scope: meta.string.interpolated.cs string.quoted.double.block.cs - match: \1 scope: punctuation.definition.string.end.cs pop: true @@ -2253,7 +2253,7 @@ contexts: inside_raw_format_string_3: - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - meta_scope: meta.string.interpolated.cs string.quoted.double.block.cs - match: \1 scope: punctuation.definition.string.end.cs pop: true @@ -2278,7 +2278,7 @@ contexts: inside_raw_format_string_4: - meta_include_prototype: false - - meta_scope: meta.string.interpolated.cs string.quoted.triple.cs + - meta_scope: meta.string.interpolated.cs string.quoted.double.block.cs - match: \1 scope: punctuation.definition.string.end.cs pop: true diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 597fec3e07..6d7be96b6f 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -3,14 +3,14 @@ // https://learn.microsoft.com/en-gb/dotnet/csharp/whats-new/csharp-11#raw-string-literals string longMessage = """ -/// ^^^ string.quoted.triple punctuation.definition.string.begin +/// ^^^ string.quoted.double.block punctuation.definition.string.begin This is a long message. It has several lines. Some are indented more than others. Some should start at the first column. Some have "quoted text" in them. -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple - punctuation +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.quoted.double.block - punctuation Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation @@ -32,7 +32,7 @@ Escapes like \0 \a \f \n \t "" are literals. /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation /// ^^ constant.character.escape.cs """; -/// ^^^ string.quoted.triple punctuation.definition.string.end +/// ^^^ string.quoted.double.block punctuation.definition.string.end longMessage = """"" This raw string literal has four """", count them: """" four! @@ -62,7 +62,7 @@ Escapes like \0 \a \f \n \t "" are literals. // - no semi-colon on the line above var location = $""" -/// ^^^^^ meta.string.interpolated string.quoted.triple +/// ^^^^^ meta.string.interpolated string.quoted.double.block /// ^^^^ punctuation.definition.string.begin /// ^ - invalid @@ -70,9 +70,9 @@ Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {Longitude}} \t {{Latitude}}} -///^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ variable.other.cs /// ^ punctuation.section.interpolation.end.cs @@ -82,9 +82,9 @@ You are at {Longitude}} \t {{Latitude}}} /// ^^^ invalid.illegal.unescaped-placeholder.cs GMT is {DateTime.Now,width:yyyyMMdd\THHmmss\Z}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -99,13 +99,13 @@ You are at {Longitude}} \t {{Latitude}}} /// ^ punctuation.section.interpolation.end.cs "{Incomplete:F"} "{Incomplete:F\"} {Brace:{}} -///^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^^ variable.other.cs /// ^^ meta.format-spec.cs @@ -127,8 +127,8 @@ You are at {Longitude}} \t {{Latitude}}} /// ^ punctuation.section.interpolation.end.cs /// ^ invalid.illegal.unescaped-placeholder.cs """; -/// <- meta.string.interpolated string.quoted.triple -///^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.end +/// <- meta.string.interpolated string.quoted.double.block +///^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.end /// ^ punctuation.terminator.statement - string // Note: Verbatim strings may look like raw strings when starting with escaped double-quotes @@ -181,15 +181,15 @@ You are at {{{Longitude}} \t {{Latitude}}} var location = $$""" /// <- storage.type.variable /// ^^^^^^^^ variable.other -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{Longitude}}} \t {Latitude}} } -///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ - constant - invalid - punctuation /// ^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ variable.other.cs @@ -199,9 +199,9 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^ - constant - invalid - punctuation GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -215,7 +215,7 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^ invalid.illegal.lone-escape.cs /// ^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs @@ -223,15 +223,15 @@ You are at {{{Longitude}}} \t {Latitude}} } /// <- storage.type.variable /// ^^^^^^^^ variable.other /// ^ invalid.illegal.reserved-char.cs -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{Longitude}}} \t {Latitude}} } -///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ - constant - invalid - punctuation /// ^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ variable.other.cs @@ -241,9 +241,9 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^ - constant - invalid - punctuation GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -257,22 +257,22 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^ invalid.illegal.lone-escape.cs /// ^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs var location = $$$""" /// <- storage.type.variable /// ^^^^^^^^ variable.other -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} -///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^ - constant - invalid - punctuation /// ^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ source.cs variable.other.cs @@ -282,9 +282,9 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^^ - constant - invalid - punctuation GMT is {{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -298,7 +298,7 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^ invalid.illegal.lone-escape.cs /// ^^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs @@ -306,15 +306,15 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// <- storage.type.variable /// ^^^^^^^^ variable.other /// ^ invalid.illegal.reserved-char.cs -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} -///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^ - constant - invalid - punctuation /// ^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ source.cs variable.other.cs @@ -324,9 +324,9 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^^ - constant - invalid - punctuation GMT is {{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -340,22 +340,22 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^ invalid.illegal.lone-escape.cs /// ^^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs var location = $$$$""" /// <- storage.type.variable /// ^^^^^^^^ variable.other -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} -///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^ - constant - invalid - punctuation /// ^^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ source.cs variable.other.cs @@ -365,9 +365,9 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^^^ - constant - invalid - punctuation GMT is {{{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -381,7 +381,7 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^ invalid.illegal.lone-escape.cs /// ^^^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs @@ -389,15 +389,15 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// <- storage.type.variable /// ^^^^^^^^ variable.other /// ^ invalid.illegal.reserved-char.cs -/// ^^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin Escapes like \0 \a \f \n \t "" are literals. ///^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - constant - invalid - punctuation You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} -///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^ - constant - invalid - punctuation /// ^^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ source.cs variable.other.cs @@ -407,9 +407,9 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^^^ - constant - invalid - punctuation GMT is {{{{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}}}! -///^^^^^^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.triple.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^ variable.other.cs /// ^ punctuation.accessor.dot.cs @@ -423,20 +423,20 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^ invalid.illegal.lone-escape.cs /// ^^^^ punctuation.section.interpolation.end.cs """; -///^^^ meta.string.interpolated.cs string.quoted.triple.cs +///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs /// ^ punctuation.terminator.statement.cs var pointMessage = $"""The point "{X}, {Y}" is {Math.Sqrt(X * X + Y * Y)} from the origin"""; -/// ^^^^ meta.string.interpolated string.quoted.triple punctuation.definition.string.begin +/// ^^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.begin /// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated -/// ^^^^^^^^^^^ string.quoted.triple - meta.interpolation +/// ^^^^^^^^^^^ string.quoted.double.block - meta.interpolation /// ^^^ meta.interpolation - string -/// ^^ string.quoted.triple - meta.interpolation +/// ^^ string.quoted.double.block - meta.interpolation /// ^^^ meta.interpolation - string -/// ^^^^^ string.quoted.triple - meta.interpolation +/// ^^^^^ string.quoted.double.block - meta.interpolation /// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.interpolation - string -/// ^^^^^^^^^^^^^^^^^^^ string.quoted.triple - meta.interpolation +/// ^^^^^^^^^^^^^^^^^^^ string.quoted.double.block - meta.interpolation /// ^ punctuation.section.interpolation.begin /// ^ variable.other /// ^ punctuation.section.interpolation.end @@ -493,7 +493,7 @@ The following example shows how newlines can improve the readability of an expre string s2 = @$$"""He said, ""This is the last \u0063hance\x0021"""; /// ^ invalid.illegal.reserved-char.cs -/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.triple - constant +/// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.string.interpolated string.quoted.double.block - constant /// ^^^^^ punctuation.definition.string.begin /// ^^ - constant.character /// ^^^^^^^^^^^^^^^^^ - constant diff --git a/C#/tests/syntax_test_Strings.cs b/C#/tests/syntax_test_Strings.cs index c491aea3e3..d65630754c 100644 --- a/C#/tests/syntax_test_Strings.cs +++ b/C#/tests/syntax_test_Strings.cs @@ -109,11 +109,11 @@ FROM foo """ SELECT * FROM some_table -/// ^^^^ meta.string.cs string.quoted.triple.cs source.sql keyword.other.dml.sql +/// ^^^^ meta.string.cs string.quoted.double.block.cs source.sql keyword.other.dml.sql """; -/// <- meta.string.cs string.quoted.triple.cs punctuation.definition.string.end.cs +/// <- meta.string.cs string.quoted.double.block.cs punctuation.definition.string.end.cs """ no sql here -/// ^^^^^^^^^^^^ meta.string.cs string.quoted.triple.cs - source.sql +/// ^^^^^^^^^^^^ meta.string.cs string.quoted.double.block.cs - source.sql """; From 5aa28d59aef0801bcd42bebdcb5be520274bbe65 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 14:52:11 +0200 Subject: [PATCH 12/14] [C#] Fix quoted strings in interpolations This commit reverts some bailout related changes to fix support of double quoted strings within interpolation expressions. --- C#/C#.sublime-syntax | 45 +++---- C#/tests/syntax_test_C#11.cs | 165 ++++++++++++++++++----- C#/tests/syntax_test_GeneralStructure.cs | 14 -- C#/tests/syntax_test_Strings.cs | 12 ++ 4 files changed, 166 insertions(+), 70 deletions(-) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index 69766774ba..990d859c14 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2024,7 +2024,9 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - include: string_interpolation_end + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true - include: string_interpolation_width - include: string_placeholder_format - include: line_of_code_in @@ -2042,11 +2044,11 @@ contexts: - meta_content_scope: constant.other.format-spec.cs - include: string_escapes - include: string_placeholder_escapes - - match: (?=[}"]) + - match: (?=\}) pop: true - - match: (?:[^}"\\](?:\\.)*)+(?=") + - match: (?:[^}"\\](?:\\.)*)*(?=") scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true + pop: 2 - match: \{ scope: invalid.illegal.unescaped-placeholder.cs @@ -2126,7 +2128,9 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - include: string_interpolation_end + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true - include: string_interpolation_width - include: verbatim_string_placeholder_format - include: line_of_code_in @@ -2144,13 +2148,13 @@ contexts: - meta_content_scope: constant.other.format-spec.cs - include: verbatim_string_escapes - include: string_placeholder_escapes - - match: (?=[}"]) + - match: (?=\}) pop: true - match: \\(?:""|[^"]) scope: constant.character.escape.cs - - match: (?:[^}"]|"")+(?="(?!")) + - match: (?:[^}"]|"")*(?="(?!")) scope: invalid.illegal.unclosed-string-placeholder.cs - pop: true + pop: 2 - match: \{ scope: invalid.illegal.unescaped-placeholder.cs @@ -2212,7 +2216,7 @@ contexts: scope: punctuation.definition.string.end.cs pop: true - match: \{{2,}|\}{1,} - scope: invalid.illegal.unescaped-placeholder.cs + scope: invalid.illegal.unexpected-token.cs - match: \{ scope: punctuation.section.interpolation.begin.cs push: inside_raw_format_string_interpolation_1 @@ -2221,7 +2225,9 @@ contexts: - clear_scopes: 1 - meta_scope: meta.interpolation.cs - meta_content_scope: source.cs - - include: string_interpolation_end + - match: \} + scope: punctuation.section.interpolation.end.cs + pop: true - include: string_interpolation_width - include: raw_string_placeholder_format - include: line_of_code_in @@ -2236,7 +2242,7 @@ contexts: scope: punctuation.section.interpolation.begin.cs push: inside_raw_format_string_interpolation_2 - match: \}{2,} - scope: invalid.illegal.unescaped-placeholder.cs + scope: invalid.illegal.unexpected-token.cs inside_raw_format_string_interpolation_2: - clear_scopes: 1 @@ -2245,8 +2251,6 @@ contexts: - match: \}{2} scope: punctuation.section.interpolation.end.cs pop: true - - match: (?=") - pop: true - include: string_interpolation_width - include: raw_string_placeholder_format - include: line_of_code_in @@ -2270,8 +2274,6 @@ contexts: - match: \}{3} scope: punctuation.section.interpolation.end.cs pop: true - - match: (?=") - pop: true - include: string_interpolation_width - include: raw_string_placeholder_format - include: line_of_code_in @@ -2295,8 +2297,6 @@ contexts: - match: \}{4} scope: punctuation.section.interpolation.end.cs pop: true - - match: (?=") - pop: true - include: string_interpolation_width - include: raw_string_placeholder_format - include: line_of_code_in @@ -2309,8 +2309,10 @@ contexts: inside_raw_string_placeholder_format: - meta_scope: meta.format-spec.cs - meta_content_scope: constant.other.format-spec.cs - - match: (?=[}"]) + - match: (?=\}) pop: true + - match: (?=") + pop: 2 - match: \\ scope: invalid.illegal.lone-escape.cs - match: \{ @@ -2355,13 +2357,6 @@ contexts: 3: keyword.operator.arithmetic.cs 4: variable.other.cs - string_interpolation_end: - - match: \} - scope: punctuation.section.interpolation.end.cs - pop: true - - match: (?=") - pop: true - string_interpolation_width: - match: \s*(?:(,)\s*(?:((-?)\d+)|({{name}}))\s*)? scope: meta.format-spec.cs diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 6d7be96b6f..70c67e59db 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -76,10 +76,10 @@ You are at {Longitude}} \t {{Latitude}}} /// ^ punctuation.section.interpolation.begin.cs /// ^^^^^^^^^ variable.other.cs /// ^ punctuation.section.interpolation.end.cs -/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^ invalid.illegal.unexpected-token.cs /// ^^ - constant.character -/// ^^ invalid.illegal.unescaped-placeholder.cs -/// ^^^ invalid.illegal.unescaped-placeholder.cs +/// ^^ invalid.illegal.unexpected-token.cs +/// ^^^ invalid.illegal.unexpected-token.cs GMT is {DateTime.Now,width:yyyyMMdd\THHmmss\Z}! ///^^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs @@ -98,34 +98,38 @@ You are at {Longitude}} \t {{Latitude}}} /// ^ invalid.illegal.lone-escape.cs /// ^ punctuation.section.interpolation.end.cs - "{Incomplete:F"} "{Incomplete:F\"} {Brace:{}} + "{In+"complete":F"} "{Incomplete:F\"} {Brace:{}} ///^^ meta.string.interpolated.cs string.quoted.double.block.cs -/// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^^ meta.string.interpolated.cs string.quoted.double.block.cs -/// ^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^^ meta.string.interpolated.cs string.quoted.double.block.cs -/// ^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string -/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs +/// ^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs +/// ^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ punctuation.section.interpolation.begin.cs -/// ^^^^^^^^^^ variable.other.cs -/// ^^ meta.format-spec.cs -/// ^ punctuation.separator.cs -/// ^ constant.other.format-spec.cs -/// ^ invalid.illegal.unescaped-placeholder.cs -/// ^ punctuation.section.interpolation.begin.cs -/// ^^^^^^^^^^ variable.other.cs -/// ^^^ meta.format-spec.cs -/// ^ punctuation.separator.cs -/// ^^ constant.other.format-spec.cs -/// ^ invalid.illegal.lone-escape.cs -/// ^ invalid.illegal.unescaped-placeholder.cs -/// ^ punctuation.section.interpolation.begin.cs -/// ^^^^^ variable.other.cs -/// ^^ meta.format-spec.cs -/// ^ punctuation.separator.cs -/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs -/// ^ punctuation.section.interpolation.end.cs -/// ^ invalid.illegal.unescaped-placeholder.cs +/// ^^ variable.other.cs +/// ^ keyword.operator.cs +/// ^^^^^^^^^^ string.quoted.double.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs +/// ^ invalid.illegal.unexpected-token.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^ invalid.illegal.unexpected-token.cs +/// ^ punctuation.section.interpolation.begin.cs +/// ^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs +/// ^ punctuation.section.interpolation.end.cs +/// ^ invalid.illegal.unexpected-token.cs """; /// <- meta.string.interpolated string.quoted.double.block ///^^^ meta.string.interpolated string.quoted.double.block punctuation.definition.string.end @@ -195,7 +199,7 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^^^^^^^^^ variable.other.cs /// ^^ punctuation.section.interpolation.end.cs /// ^^^^^^ - constant - invalid - punctuation -/// ^^ invalid.illegal.unescaped-placeholder.cs +/// ^^ invalid.illegal.unexpected-token.cs /// ^ - constant - invalid - punctuation GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! @@ -214,6 +218,39 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^ invalid.illegal.lone-escape.cs /// ^ invalid.illegal.lone-escape.cs /// ^^ punctuation.section.interpolation.end.cs + + "{{In+"complete":F"}} "{{Incomplete:F\"}} {{Brace:{}}} +///^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs +/// ^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs +/// ^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^ variable.other.cs +/// ^ keyword.operator.cs +/// ^^^^^^^^^^ string.quoted.double.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs +/// ^^ invalid.illegal.unexpected-token.cs +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^ invalid.illegal.unexpected-token.cs +/// ^^ punctuation.section.interpolation.begin.cs +/// ^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs +/// ^^ punctuation.section.interpolation.end.cs +/// ^ - invalid.illegal """; ///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs @@ -237,7 +274,7 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^^^^^^^^^ variable.other.cs /// ^^ punctuation.section.interpolation.end.cs /// ^^^^^^ - constant - invalid - punctuation -/// ^^ invalid.illegal.unescaped-placeholder.cs +/// ^^ invalid.illegal.unexpected-token.cs /// ^ - constant - invalid - punctuation GMT is {{DateTime.Now,width:yyyyMMdd\THHmmss\Z}}! @@ -297,6 +334,39 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^ invalid.illegal.lone-escape.cs /// ^ invalid.illegal.lone-escape.cs /// ^^^ punctuation.section.interpolation.end.cs + + "{{{In+"complete":F"}}} "{{{Incomplete:F\"}}} {{{Brace:{}}}} +///^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs +/// ^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs +/// ^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^ variable.other.cs +/// ^ keyword.operator.cs +/// ^^^^^^^^^^ string.quoted.double.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs +/// ^^^ invalid.illegal.unexpected-token.cs +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^ invalid.illegal.unexpected-token.cs +/// ^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs +/// ^^^ punctuation.section.interpolation.end.cs +/// ^ - invalid.illegal """; ///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs @@ -380,6 +450,39 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^ invalid.illegal.lone-escape.cs /// ^ invalid.illegal.lone-escape.cs /// ^^^^ punctuation.section.interpolation.end.cs + + "{{{{In+"complete":F"}}}} "{{{{Incomplete:F\"}}}} {{{{Brace:{}}}}} +///^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs +/// ^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs +/// ^^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^^^^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^^^^^^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs - string +/// ^^ meta.string.interpolated.cs string.quoted.double.block.cs +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^ variable.other.cs +/// ^ keyword.operator.cs +/// ^^^^^^^^^^ string.quoted.double.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs +/// ^^^^ invalid.illegal.unexpected-token.cs +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^^^^^^ variable.other.cs +/// ^^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^^ constant.other.format-spec.cs +/// ^ invalid.illegal.lone-escape.cs +/// ^^^^ invalid.illegal.unexpected-token.cs +/// ^^^^ punctuation.section.interpolation.begin.cs +/// ^^^^^ variable.other.cs +/// ^^ meta.format-spec.cs +/// ^ punctuation.separator.cs +/// ^ constant.other.format-spec.cs invalid.illegal.unescaped-placeholder.cs +/// ^^^ punctuation.section.interpolation.end.cs +/// ^ - invalid.illegal """; ///^^^ meta.string.interpolated.cs string.quoted.double.block.cs ///^^^ punctuation.definition.string.end.cs diff --git a/C#/tests/syntax_test_GeneralStructure.cs b/C#/tests/syntax_test_GeneralStructure.cs index 49889fbab3..6c260f33fd 100644 --- a/C#/tests/syntax_test_GeneralStructure.cs +++ b/C#/tests/syntax_test_GeneralStructure.cs @@ -1318,13 +1318,6 @@ void TestMe () { /// ^^ constant.character.escape.cs /// ^ invalid.illegal.unescaped-placeholder.cs /// ^^ constant.character.escape.cs - Console.WriteLine(@$"GMT is {DateTime.Now"); -/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec -/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec - Console.WriteLine(@$"GMT is {DateTime.Now"""); -/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec -/// ^^ meta.string.interpolated.cs string.quoted.double.verbatim.cs constant.character.escape.cs -/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec Console.WriteLine(@$"GMT is {DateTime.Now:"); /// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^ invalid.illegal.unclosed-string-placeholder.cs @@ -1344,13 +1337,6 @@ void TestMe () { /// ^^ constant.character.escape.cs /// ^ invalid.illegal.unescaped-placeholder.cs /// ^^ constant.character.escape.cs - Console.WriteLine($"GMT is {DateTime.Now"); -/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec -/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec - Console.WriteLine($"GMT is {DateTime.Now"""); -/// ^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec -/// ^ meta.string.interpolated punctuation.definition.string.end - meta.interpolation - meta.format-spec -/// ^^ meta.string.cs string.quoted.double.cs punctuation Console.WriteLine($"GMT is {DateTime.Now:"); /// ^^^^^^^^^^^^^^ meta.string.interpolated meta.interpolation - meta.format-spec /// ^ invalid.illegal.unclosed-string-placeholder.cs diff --git a/C#/tests/syntax_test_Strings.cs b/C#/tests/syntax_test_Strings.cs index d65630754c..14e10129ca 100644 --- a/C#/tests/syntax_test_Strings.cs +++ b/C#/tests/syntax_test_Strings.cs @@ -46,6 +46,18 @@ /// ^^^^^^ meta.string.interpolated.cs string.quoted.double.cs var interpolated_yes = $"foo {bar} foo"; /// ^^^^^^^^^^^^^^^^ meta.string.interpolated.cs +var interpolated_quotes = $"|{"Left",-7}|{"Right",7}|"; +/// ^^^ meta.string.interpolated.cs +/// ^ meta.string.interpolated.cs meta.interpolation.cs punctuation.section.interpolation.begin.cs +/// ^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs string.quoted.double.cs +/// ^^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs - string +/// ^ meta.string.interpolated.cs meta.interpolation.cs punctuation.section.interpolation.end.cs +/// ^ meta.string.interpolated.cs string.quoted.double.cs +/// ^ meta.string.interpolated.cs meta.interpolation.cs punctuation.section.interpolation.begin.cs +/// ^^^^^^^ meta.string.interpolated.cs meta.interpolation.cs meta.string.cs string.quoted.double.cs +/// ^^ meta.string.interpolated.cs meta.interpolation.cs meta.format-spec.cs - string +/// ^ meta.string.interpolated.cs meta.interpolation.cs punctuation.section.interpolation.end.cs +/// ^^ meta.string.interpolated.cs string.quoted.double.cs var verbatim_singleline = @"foo"; /// ^^^^^^ meta.string.cs string.quoted.double.verbatim.cs - meta.string.interpolated var verbatim_singleline_interpolated_none = $@"foo bar"; From 2b8fef64339be828bfd21d6015b7c84ecd1f13a7 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Sun, 29 Mar 2026 21:11:58 +0200 Subject: [PATCH 13/14] [C#] Adjust tests --- C#/tests/syntax_test_C#11.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/C#/tests/syntax_test_C#11.cs b/C#/tests/syntax_test_C#11.cs index 70c67e59db..c51431fcc0 100644 --- a/C#/tests/syntax_test_C#11.cs +++ b/C#/tests/syntax_test_C#11.cs @@ -110,7 +110,7 @@ You are at {Longitude}} \t {{Latitude}}} /// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^ punctuation.section.interpolation.begin.cs /// ^^ variable.other.cs -/// ^ keyword.operator.cs +/// ^ keyword.operator.arithmetic.cs /// ^^^^^^^^^^ string.quoted.double.cs /// ^^ meta.format-spec.cs /// ^ punctuation.separator.cs @@ -231,7 +231,7 @@ You are at {{{Longitude}}} \t {Latitude}} } /// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^ punctuation.section.interpolation.begin.cs /// ^^ variable.other.cs -/// ^ keyword.operator.cs +/// ^ keyword.operator.arithmetic.cs /// ^^^^^^^^^^ string.quoted.double.cs /// ^^ meta.format-spec.cs /// ^ punctuation.separator.cs @@ -347,7 +347,7 @@ You are at {{{{{Longitude}}}}} \t {{Latitude}}} }} /// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^ punctuation.section.interpolation.begin.cs /// ^^ variable.other.cs -/// ^ keyword.operator.cs +/// ^ keyword.operator.arithmetic.cs /// ^^^^^^^^^^ string.quoted.double.cs /// ^^ meta.format-spec.cs /// ^ punctuation.separator.cs @@ -463,7 +463,7 @@ You are at {{{{{{{Longitude}}}}}}} \t {{{Latitude}}}} }}} /// ^^ meta.string.interpolated.cs string.quoted.double.block.cs /// ^^^^ punctuation.section.interpolation.begin.cs /// ^^ variable.other.cs -/// ^ keyword.operator.cs +/// ^ keyword.operator.arithmetic.cs /// ^^^^^^^^^^ string.quoted.double.cs /// ^^ meta.format-spec.cs /// ^ punctuation.separator.cs From e6f1360ad47e491602e719ed8fdf6c9a86c40209 Mon Sep 17 00:00:00 2001 From: deathaxe Date: Mon, 30 Mar 2026 21:14:36 +0200 Subject: [PATCH 14/14] [C#] Add string_prototype context This commit helps 3rd-party syntaxes to extend C# and add common patterns to string literals by adding a `string_prototype` context. --- C#/C#.sublime-syntax | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/C#/C#.sublime-syntax b/C#/C#.sublime-syntax index f33014827d..575c190d5b 100644 --- a/C#/C#.sublime-syntax +++ b/C#/C#.sublime-syntax @@ -2031,6 +2031,7 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_escapes - include: string_placeholder_escapes - include: string_placeholders @@ -2057,6 +2058,7 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_escapes - include: string_placeholder_escapes - match: \{ @@ -2109,6 +2111,7 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_placeholder_escapes - include: string_placeholders - include: extended_verbatim_string_placeholders @@ -2121,6 +2124,7 @@ contexts: - include: verbatim_string_escapes - match: (?=") pop: true + - include: string_prototype - include: string_placeholder_escapes - include: string_placeholders - include: extended_verbatim_string_placeholders @@ -2149,6 +2153,7 @@ contexts: - match: '"' scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_placeholder_escapes - include: verbatim_format_string_interpolations @@ -2160,6 +2165,7 @@ contexts: - include: verbatim_string_escapes - match: (?=") pop: true + - include: string_prototype - include: string_placeholder_escapes - include: verbatim_format_string_interpolations - match: (?=\S) @@ -2218,6 +2224,7 @@ contexts: - match: '"""' scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_placeholder_escapes - include: string_placeholders - include: extended_raw_string_placeholders @@ -2229,6 +2236,7 @@ contexts: with_prototype: - match: (?=""") pop: true + - include: string_prototype - match: (?=\S) pop: true @@ -2238,6 +2246,7 @@ contexts: - match: \1 scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - include: string_placeholder_escapes - include: string_placeholders - include: extended_raw_string_placeholders @@ -2263,6 +2272,7 @@ contexts: - match: \1 scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - match: \{{2,}|\}{1,} scope: invalid.illegal.unexpected-token.cs - match: \{ @@ -2286,6 +2296,7 @@ contexts: - match: \1 scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - match: \{{2}(?!\{) scope: punctuation.section.interpolation.begin.cs push: inside_raw_format_string_interpolation_2 @@ -2309,6 +2320,7 @@ contexts: - match: \1 scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - match: \{{3}(?!\{) scope: punctuation.section.interpolation.begin.cs push: inside_raw_format_string_interpolation_3 @@ -2332,6 +2344,7 @@ contexts: - match: \1 scope: punctuation.definition.string.end.cs pop: true + - include: string_prototype - match: \{{4}(?!\{) scope: punctuation.section.interpolation.begin.cs push: inside_raw_format_string_interpolation_4 @@ -2414,6 +2427,8 @@ contexts: 3: keyword.operator.arithmetic.cs 4: variable.other.cs + string_prototype: [] + ###[ INITIALIZERS ]############################################################ initializer_constructor: