Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDScript: Fix highlighting escapes in multiline raw strings #90419

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions modules/gdscript/editor/gdscript_highlighter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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) {
Expand All @@ -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;
}
}
Expand All @@ -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) {
Expand Down Expand Up @@ -242,15 +246,15 @@ 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;
}

from++;

if (!in_raw_string) {
if (!color_regions[in_region].r_prefix) {
int esc_len = 0;
if (str[from] == 'u') {
esc_len = 4;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<Script> scr = _get_edited_resource();
if (scr.is_valid()) {
Expand Down Expand Up @@ -927,7 +931,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {
}
}

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) {
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) {
ERR_FAIL_COND_MSG(p_start_key.is_empty(), "Color region start key cannot be empty.");
ERR_FAIL_COND_MSG(!is_symbol(p_start_key[0]), "Color region start key must start with a symbol.");

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

int at = 0;
for (int i = 0; i < color_regions.size(); i++) {
ERR_FAIL_COND_MSG(color_regions[i].start_key == p_start_key, "Color region with start key '" + p_start_key + "' already exists.");
if (p_start_key.length() < color_regions[i].start_key.length()) {
for (const ColorRegion &region : color_regions) {
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.");
if (p_start_key.length() < region.start_key.length()) {
at++;
} else {
break;
Expand All @@ -951,6 +955,9 @@ void GDScriptSyntaxHighlighter::add_color_region(ColorRegion::Type p_type, const
color_region.start_key = p_start_key;
color_region.end_key = p_end_key;
color_region.line_only = p_line_only;
color_region.r_prefix = p_r_prefix;
color_region.is_string = p_type == ColorRegion::TYPE_STRING || p_type == ColorRegion::TYPE_MULTILINE_STRING;
color_region.is_comment = p_type == ColorRegion::TYPE_COMMENT || p_type == ColorRegion::TYPE_CODE_REGION;
color_regions.insert(at, color_region);
clear_highlighting_cache();
}
Expand Down
5 changes: 4 additions & 1 deletion modules/gdscript/editor/gdscript_highlighter.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
String start_key;
String end_key;
bool line_only = false;
bool r_prefix = false;
bool is_string = false; // `TYPE_STRING` or `TYPE_MULTILINE_STRING`.
bool is_comment = false; // `TYPE_COMMENT` or `TYPE_CODE_REGION`.
};
Vector<ColorRegion> color_regions;
HashMap<int, int> color_region_cache;
Expand Down Expand Up @@ -103,7 +106,7 @@ class GDScriptSyntaxHighlighter : public EditorSyntaxHighlighter {
Color comment_marker_colors[COMMENT_MARKER_MAX];
HashMap<String, CommentMarkerLevel> comment_markers;

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);
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);

public:
virtual void _update_cache() override;
Expand Down
Loading