From 98dac9e39c77c663691386228f67adf1a3b37ec1 Mon Sep 17 00:00:00 2001 From: Danil Alexeev Date: Tue, 9 Apr 2024 10:21:10 +0300 Subject: [PATCH] GDScript: Fix highlighting escapes in multiline raw strings --- .../gdscript/editor/gdscript_highlighter.cpp | 41 +++++++++++-------- .../gdscript/editor/gdscript_highlighter.h | 5 ++- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index b4f4e879d0e..f83b784f85c 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -53,7 +53,6 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l bool in_keyword = false; bool in_word = false; bool in_number = false; - bool in_raw_string = false; bool in_node_path = false; bool in_node_ref = false; bool in_annotation = false; @@ -127,6 +126,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (from != line_length) { // Check if we are in entering a region. if (in_region == -1) { + const bool r_prefix = from > 0 && str[from - 1] == 'r'; for (int c = 0; c < color_regions.size(); c++) { // Check there is enough room. int chars_left = line_length - from; @@ -136,6 +136,10 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l continue; } + if (color_regions[c].is_string && color_regions[c].r_prefix != r_prefix) { + continue; + } + // Search the line. bool match = true; const char32_t *start_key = color_regions[c].start_key.get_data(); @@ -154,7 +158,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l // Check if it's the whole line. if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) { // Don't skip comments, for highlighting markers. - if (color_regions[in_region].type == ColorRegion::TYPE_COMMENT) { + if (color_regions[in_region].is_comment) { break; } if (from + end_key_length > line_length) { @@ -176,7 +180,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } // Don't skip comments, for highlighting markers. - if (j == line_length && color_regions[in_region].type != ColorRegion::TYPE_COMMENT) { + if (j == line_length && !color_regions[in_region].is_comment) { continue; } } @@ -198,7 +202,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l highlighter_info["color"] = region_color; color_map[j] = highlighter_info; - if (color_regions[in_region].type == ColorRegion::TYPE_COMMENT) { + if (color_regions[in_region].is_comment) { int marker_start_pos = from; int marker_len = 0; while (from <= line_length) { @@ -242,7 +246,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } if (str[from] == '\\') { - if (!in_raw_string) { + if (!color_regions[in_region].r_prefix) { Dictionary escape_char_highlighter_info; escape_char_highlighter_info["color"] = symbol_color; color_map[from] = escape_char_highlighter_info; @@ -250,7 +254,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l from++; - if (!in_raw_string) { + if (!color_regions[in_region].r_prefix) { int esc_len = 0; if (str[from] == 'u') { esc_len = 4; @@ -556,12 +560,6 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l } } - if (!in_raw_string && in_region == -1 && str[j] == 'r' && j < line_length - 1 && (str[j + 1] == '"' || str[j + 1] == '\'')) { - in_raw_string = true; - } else if (in_raw_string && in_region == -1) { - in_raw_string = false; - } - // Keep symbol color for binary '&&'. In the case of '&&&' use StringName color for the last ampersand. if (!in_string_name && in_region == -1 && str[j] == '&' && !is_binary_op) { if (j >= 2 && str[j - 1] == '&' && str[j - 2] != '&' && prev_is_binary_op) { @@ -593,7 +591,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l in_annotation = false; } - if (in_raw_string) { + const bool in_raw_string_prefix = in_region == -1 && str[j] == 'r' && j + 1 < line_length && (str[j + 1] == '"' || str[j + 1] == '\''); + + if (in_raw_string_prefix) { color = string_color; } else if (in_node_ref) { next_type = NODE_REF; @@ -795,6 +795,10 @@ void GDScriptSyntaxHighlighter::_update_cache() { add_color_region(ColorRegion::TYPE_STRING, "'", "'", string_color); add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "\"\"\"", "\"\"\"", string_color); add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "'''", "'''", string_color); + add_color_region(ColorRegion::TYPE_STRING, "\"", "\"", string_color, false, true); + add_color_region(ColorRegion::TYPE_STRING, "'", "'", string_color, false, true); + add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "\"\"\"", "\"\"\"", string_color, false, true); + add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "'''", "'''", string_color, false, true); const Ref