Skip to content

Commit a7b8602

Browse files
committed
Merge pull request godotengine#90419 from dalexeev/gds-fix-hl-esc-multiline-r-strings
GDScript: Fix highlighting escapes in multiline raw strings
2 parents a445f6b + 98dac9e commit a7b8602

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

modules/gdscript/editor/gdscript_highlighter.cpp

+24-17
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
5353
bool in_keyword = false;
5454
bool in_word = false;
5555
bool in_number = false;
56-
bool in_raw_string = false;
5756
bool in_node_path = false;
5857
bool in_node_ref = false;
5958
bool in_annotation = false;
@@ -127,6 +126,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
127126
if (from != line_length) {
128127
// Check if we are in entering a region.
129128
if (in_region == -1) {
129+
const bool r_prefix = from > 0 && str[from - 1] == 'r';
130130
for (int c = 0; c < color_regions.size(); c++) {
131131
// Check there is enough room.
132132
int chars_left = line_length - from;
@@ -136,6 +136,10 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
136136
continue;
137137
}
138138

139+
if (color_regions[c].is_string && color_regions[c].r_prefix != r_prefix) {
140+
continue;
141+
}
142+
139143
// Search the line.
140144
bool match = true;
141145
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
154158
// Check if it's the whole line.
155159
if (end_key_length == 0 || color_regions[c].line_only || from + end_key_length > line_length) {
156160
// Don't skip comments, for highlighting markers.
157-
if (color_regions[in_region].type == ColorRegion::TYPE_COMMENT) {
161+
if (color_regions[in_region].is_comment) {
158162
break;
159163
}
160164
if (from + end_key_length > line_length) {
@@ -176,7 +180,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
176180
}
177181

178182
// Don't skip comments, for highlighting markers.
179-
if (j == line_length && color_regions[in_region].type != ColorRegion::TYPE_COMMENT) {
183+
if (j == line_length && !color_regions[in_region].is_comment) {
180184
continue;
181185
}
182186
}
@@ -198,7 +202,7 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
198202
highlighter_info["color"] = region_color;
199203
color_map[j] = highlighter_info;
200204

201-
if (color_regions[in_region].type == ColorRegion::TYPE_COMMENT) {
205+
if (color_regions[in_region].is_comment) {
202206
int marker_start_pos = from;
203207
int marker_len = 0;
204208
while (from <= line_length) {
@@ -242,15 +246,15 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
242246
}
243247

244248
if (str[from] == '\\') {
245-
if (!in_raw_string) {
249+
if (!color_regions[in_region].r_prefix) {
246250
Dictionary escape_char_highlighter_info;
247251
escape_char_highlighter_info["color"] = symbol_color;
248252
color_map[from] = escape_char_highlighter_info;
249253
}
250254

251255
from++;
252256

253-
if (!in_raw_string) {
257+
if (!color_regions[in_region].r_prefix) {
254258
int esc_len = 0;
255259
if (str[from] == 'u') {
256260
esc_len = 4;
@@ -556,12 +560,6 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l
556560
}
557561
}
558562

559-
if (!in_raw_string && in_region == -1 && str[j] == 'r' && j < line_length - 1 && (str[j + 1] == '"' || str[j + 1] == '\'')) {
560-
in_raw_string = true;
561-
} else if (in_raw_string && in_region == -1) {
562-
in_raw_string = false;
563-
}
564-
565563
// Keep symbol color for binary '&&'. In the case of '&&&' use StringName color for the last ampersand.
566564
if (!in_string_name && in_region == -1 && str[j] == '&' && !is_binary_op) {
567565
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
593591
in_annotation = false;
594592
}
595593

596-
if (in_raw_string) {
594+
const bool in_raw_string_prefix = in_region == -1 && str[j] == 'r' && j + 1 < line_length && (str[j + 1] == '"' || str[j + 1] == '\'');
595+
596+
if (in_raw_string_prefix) {
597597
color = string_color;
598598
} else if (in_node_ref) {
599599
next_type = NODE_REF;
@@ -795,6 +795,10 @@ void GDScriptSyntaxHighlighter::_update_cache() {
795795
add_color_region(ColorRegion::TYPE_STRING, "'", "'", string_color);
796796
add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "\"\"\"", "\"\"\"", string_color);
797797
add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "'''", "'''", string_color);
798+
add_color_region(ColorRegion::TYPE_STRING, "\"", "\"", string_color, false, true);
799+
add_color_region(ColorRegion::TYPE_STRING, "'", "'", string_color, false, true);
800+
add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "\"\"\"", "\"\"\"", string_color, false, true);
801+
add_color_region(ColorRegion::TYPE_MULTILINE_STRING, "'''", "'''", string_color, false, true);
798802

799803
const Ref<Script> scr = _get_edited_resource();
800804
if (scr.is_valid()) {
@@ -927,7 +931,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
927931
}
928932
}
929933

930-
void GDScriptSyntaxHighlighter::add_color_region(ColorRegion::Type p_type, const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only) {
934+
void GDScriptSyntaxHighlighter::add_color_region(ColorRegion::Type p_type, const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only, bool p_r_prefix) {
931935
ERR_FAIL_COND_MSG(p_start_key.is_empty(), "Color region start key cannot be empty.");
932936
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[0]), "Color region start key must start with a symbol.");
933937

@@ -936,9 +940,9 @@ void GDScriptSyntaxHighlighter::add_color_region(ColorRegion::Type p_type, const
936940
}
937941

938942
int at = 0;
939-
for (int i = 0; i < color_regions.size(); i++) {
940-
ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "Color region with start key '" + p_start_key + "' already exists.");
941-
if (p_start_key.length() < color_regions[i].start_key.length()) {
943+
for (const ColorRegion &region : color_regions) {
944+
ERR_FAIL_COND_MSG(region.start_key == p_start_key && region.r_prefix == p_r_prefix, "Color region with start key '" + p_start_key + "' already exists.");
945+
if (p_start_key.length() < region.start_key.length()) {
942946
at++;
943947
} else {
944948
break;
@@ -951,6 +955,9 @@ void GDScriptSyntaxHighlighter::add_color_region(ColorRegion::Type p_type, const
951955
color_region.start_key = p_start_key;
952956
color_region.end_key = p_end_key;
953957
color_region.line_only = p_line_only;
958+
color_region.r_prefix = p_r_prefix;
959+
color_region.is_string = p_type == ColorRegion::TYPE_STRING || p_type == ColorRegion::TYPE_MULTILINE_STRING;
960+
color_region.is_comment = p_type == ColorRegion::TYPE_COMMENT || p_type == ColorRegion::TYPE_CODE_REGION;
954961
color_regions.insert(at, color_region);
955962
clear_highlighting_cache();
956963
}

modules/gdscript/editor/gdscript_highlighter.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
5252
String start_key;
5353
String end_key;
5454
bool line_only = false;
55+
bool r_prefix = false;
56+
bool is_string = false; // `TYPE_STRING` or `TYPE_MULTILINE_STRING`.
57+
bool is_comment = false; // `TYPE_COMMENT` or `TYPE_CODE_REGION`.
5558
};
5659
Vector<ColorRegion> color_regions;
5760
HashMap<int, int> color_region_cache;
@@ -103,7 +106,7 @@ class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
103106
Color comment_marker_colors[COMMENT_MARKER_MAX];
104107
HashMap<String, CommentMarkerLevel> comment_markers;
105108

106-
void add_color_region(ColorRegion::Type p_type, const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false);
109+
void add_color_region(ColorRegion::Type p_type, const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false, bool p_r_prefix = false);
107110

108111
public:
109112
virtual void _update_cache() override;

0 commit comments

Comments
 (0)