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

Highlight doc comments in a different color #72751

Merged
merged 1 commit into from
Oct 9, 2023
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
1 change: 1 addition & 0 deletions core/object/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ class ScriptLanguage : public Object {
virtual void get_reserved_words(List<String> *p_words) const = 0;
virtual bool is_control_flow_keyword(String p_string) const = 0;
virtual void get_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_doc_comment_delimiters(List<String> *p_delimiters) const = 0;
virtual void get_string_delimiters(List<String> *p_delimiters) const = 0;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const { return Ref<Script>(); }
virtual Vector<ScriptTemplate> get_built_in_templates(StringName p_object) { return Vector<ScriptTemplate>(); }
Expand Down
1 change: 1 addition & 0 deletions core/object/script_language_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ void ScriptLanguageExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_reserved_words);
GDVIRTUAL_BIND(_is_control_flow_keyword, "keyword");
GDVIRTUAL_BIND(_get_comment_delimiters);
GDVIRTUAL_BIND(_get_doc_comment_delimiters);
GDVIRTUAL_BIND(_get_string_delimiters);
GDVIRTUAL_BIND(_make_template, "template", "class_name", "base_class_name");
GDVIRTUAL_BIND(_get_built_in_templates, "object");
Expand Down
10 changes: 10 additions & 0 deletions core/object/script_language_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,16 @@ class ScriptLanguageExtension : public ScriptLanguage {
}
}

GDVIRTUAL0RC(Vector<String>, _get_doc_comment_delimiters)

virtual void get_doc_comment_delimiters(List<String> *p_words) const override {
Vector<String> ret;
GDVIRTUAL_CALL(_get_doc_comment_delimiters, ret);
for (int i = 0; i < ret.size(); i++) {
p_words->push_back(ret[i]);
}
}

GDVIRTUAL0RC(Vector<String>, _get_string_delimiters)

virtual void get_string_delimiters(List<String> *p_words) const override {
Expand Down
3 changes: 3 additions & 0 deletions doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -953,6 +953,9 @@
<member name="text_editor/theme/highlighting/current_line_color" type="Color" setter="" getter="">
The script editor's background color for the line the caret is currently on. This should be set to a translucent color so that it can display on top of other line color modifiers such as [member text_editor/theme/highlighting/mark_color].
</member>
<member name="text_editor/theme/highlighting/doc_comment_color" type="Color" setter="" getter="">
The script editor's documentation comment color. In GDScript, this is used for comments starting with [code]##[/code]. In C#, this is used for comments starting with [code]///[/code] or [code]/**[/code].
</member>
<member name="text_editor/theme/highlighting/engine_type_color" type="Color" setter="" getter="">
The script editor's engine type color ([Vector2], [Vector3], [Color], ...).
</member>
Expand Down
5 changes: 5 additions & 0 deletions doc/classes/ScriptLanguageExtension.xml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@
<description>
</description>
</method>
<method name="_get_doc_comment_delimiters" qualifiers="virtual const">
<return type="PackedStringArray" />
<description>
</description>
</method>
<method name="_get_extension" qualifiers="virtual const">
<return type="String" />
<description>
Expand Down
3 changes: 3 additions & 0 deletions editor/code_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,8 @@ void CodeTextEditor::_complete_request() {
font_color = get_theme_color(e.theme_color_name, SNAME("Editor"));
} else if (e.insert_text.begins_with("\"") || e.insert_text.begins_with("\'")) {
font_color = completion_string_color;
} else if (e.insert_text.begins_with("##") || e.insert_text.begins_with("///")) {
font_color = completion_doc_comment_color;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, when would autocompletion ever use ## or /// as a prefix? And why not /**? I see this already exist for normal comment delimiters, but I don't know where those might appear in autocomplete either...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember comments ever being auto-completed either. But I didn't dare remove this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} else if (e.insert_text.begins_with("#") || e.insert_text.begins_with("//")) {
font_color = completion_comment_color;
}
Expand Down Expand Up @@ -1026,6 +1028,7 @@ void CodeTextEditor::update_editor_settings() {
completion_font_color = EDITOR_GET("text_editor/theme/highlighting/completion_font_color");
completion_string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
completion_comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
completion_doc_comment_color = EDITOR_GET("text_editor/theme/highlighting/doc_comment_color");

// Appearance: Caret
text_editor->set_caret_type((TextEdit::CaretType)EDITOR_GET("text_editor/appearance/caret/type").operator int());
Expand Down
1 change: 1 addition & 0 deletions editor/code_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ class CodeTextEditor : public VBoxContainer {
Color completion_font_color;
Color completion_string_color;
Color completion_comment_color;
Color completion_doc_comment_color;
CodeTextEditorCodeCompleteFunc code_complete_func;
void *code_complete_ud = nullptr;

Expand Down
1 change: 1 addition & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@ void EditorSettings::_load_godot2_text_editor_theme() {
_initial_set("text_editor/theme/highlighting/engine_type_color", Color(0.51, 0.83, 1.0));
_initial_set("text_editor/theme/highlighting/user_type_color", Color(0.42, 0.67, 0.93));
_initial_set("text_editor/theme/highlighting/comment_color", Color(0.4, 0.4, 0.4));
_initial_set("text_editor/theme/highlighting/doc_comment_color", Color(0.5, 0.6, 0.7));
_initial_set("text_editor/theme/highlighting/string_color", Color(0.94, 0.43, 0.75));
_initial_set("text_editor/theme/highlighting/background_color", Color(0.13, 0.12, 0.15));
_initial_set("text_editor/theme/highlighting/completion_background_color", Color(0.17, 0.16, 0.2));
Expand Down
4 changes: 3 additions & 1 deletion editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2215,7 +2215,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {

// adaptive script theme constants
// for comments and elements with lower relevance
const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
const Color dim_color = Color(font_color, 0.5);

const float mono_value = mono_color.r;
const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.07);
Expand All @@ -2229,6 +2229,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color engine_type_color = dark_theme ? Color(0.56, 1, 0.86) : Color(0.11, 0.55, 0.4);
const Color user_type_color = dark_theme ? Color(0.78, 1, 0.93) : Color(0.18, 0.45, 0.4);
const Color comment_color = dark_theme ? dim_color : Color(0.08, 0.08, 0.08, 0.5);
const Color doc_comment_color = dark_theme ? Color(0.6, 0.7, 0.8, 0.8) : Color(0.15, 0.15, 0.4, 0.7);
const Color string_color = dark_theme ? Color(1, 0.93, 0.63) : Color(0.6, 0.42, 0);

// Use the brightest background color on a light theme (which generally uses a negative contrast rate).
Expand Down Expand Up @@ -2272,6 +2273,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/theme/highlighting/engine_type_color", engine_type_color, true);
setting->set_initial_value("text_editor/theme/highlighting/user_type_color", user_type_color, true);
setting->set_initial_value("text_editor/theme/highlighting/comment_color", comment_color, true);
setting->set_initial_value("text_editor/theme/highlighting/doc_comment_color", doc_comment_color, true);
setting->set_initial_value("text_editor/theme/highlighting/string_color", string_color, true);
setting->set_initial_value("text_editor/theme/highlighting/background_color", te_background_color, true);
setting->set_initial_value("text_editor/theme/highlighting/completion_background_color", completion_background_color, true);
Expand Down
11 changes: 10 additions & 1 deletion editor/plugins/editor_preview_plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
Color text_color = EDITOR_GET("text_editor/theme/highlighting/text_color");
Color symbol_color = EDITOR_GET("text_editor/theme/highlighting/symbol_color");
Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color");
Color doc_comment_color = EDITOR_GET("text_editor/theme/highlighting/doc_comment_color");

if (bg_color.a == 0) {
bg_color = Color(0, 0, 0, 0);
Expand All @@ -513,18 +514,25 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
bool in_control_flow_keyword = false;
bool in_keyword = false;
bool in_comment = false;
bool in_doc_comment = false;
for (int i = 0; i < code.length(); i++) {
char32_t c = code[i];
if (c > 32) {
if (col < thumbnail_size) {
Color color = text_color;

if (c == '#') {
in_comment = true;
if (i < code.length() - 1 && code[i + 1] == '#') {
in_doc_comment = true;
} else {
in_comment = true;
}
}

if (in_comment) {
color = comment_color;
} else if (in_doc_comment) {
color = doc_comment_color;
} else {
if (is_symbol(c)) {
//make symbol a little visible
Expand Down Expand Up @@ -569,6 +577,7 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,

if (c == '\n') {
in_comment = false;
in_doc_comment = false;

col = x0;
line++;
Expand Down
10 changes: 10 additions & 0 deletions editor/plugins/script_editor_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ void EditorStandardSyntaxHighlighter::_update_cache() {
highlighter->add_color_region(beg, end, comment_color, end.is_empty());
}

/* Doc comments */
const Color doc_comment_color = EDITOR_GET("text_editor/theme/highlighting/doc_comment_color");
List<String> doc_comments;
scr->get_language()->get_doc_comment_delimiters(&doc_comments);
for (const String &doc_comment : doc_comments) {
String beg = doc_comment.get_slice(" ", 0);
String end = doc_comment.get_slice_count(" ") > 1 ? doc_comment.get_slice(" ", 1) : String();
highlighter->add_color_region(beg, end, doc_comment_color, end.is_empty());
}

/* Strings */
const Color string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
List<String> strings;
Expand Down
15 changes: 14 additions & 1 deletion editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,10 @@ void ScriptTextEditor::_set_theme_for_script() {
}
}

text_edit->clear_comment_delimiters();

List<String> comments;
script->get_language()->get_comment_delimiters(&comments);
text_edit->clear_comment_delimiters();
for (const String &comment : comments) {
String beg = comment.get_slice(" ", 0);
String end = comment.get_slice_count(" ") > 1 ? comment.get_slice(" ", 1) : String();
Expand All @@ -246,6 +247,18 @@ void ScriptTextEditor::_set_theme_for_script() {
text_edit->add_auto_brace_completion_pair(beg, end);
}
}

List<String> doc_comments;
script->get_language()->get_doc_comment_delimiters(&doc_comments);
for (const String &doc_comment : doc_comments) {
String beg = doc_comment.get_slice(" ", 0);
String end = doc_comment.get_slice_count(" ") > 1 ? doc_comment.get_slice(" ", 1) : String();
text_edit->add_comment_delimiter(beg, end, end.is_empty());

if (!end.is_empty() && !text_edit->has_auto_brace_completion_open_key(beg)) {
text_edit->add_auto_brace_completion_pair(beg, end);
}
}
}

void ScriptTextEditor::_show_errors_panel(bool p_show) {
Expand Down
16 changes: 13 additions & 3 deletions modules/gdscript/editor/gdscript_highlighter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,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].start_key == "#") {
if (color_regions[in_region].start_key.begins_with("#")) {
break;
}
if (from + end_key_length > line_length) {
Expand All @@ -171,7 +171,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].start_key != "#") {
if (j == line_length && !color_regions[in_region].start_key.begins_with("#")) {
continue;
}
}
Expand All @@ -193,7 +193,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].start_key == "#") {
if (color_regions[in_region].start_key.begins_with("#")) {
int marker_start_pos = from;
int marker_len = 0;
while (from <= line_length) {
Expand Down Expand Up @@ -740,6 +740,16 @@ void GDScriptSyntaxHighlighter::_update_cache() {
add_color_region(beg, end, comment_color, end.is_empty());
}

/* Doc comments */
const Color doc_comment_color = EDITOR_GET("text_editor/theme/highlighting/doc_comment_color");
List<String> doc_comments;
gdscript->get_doc_comment_delimiters(&doc_comments);
for (const String &doc_comment : doc_comments) {
String beg = doc_comment.get_slice(" ", 0);
String end = doc_comment.get_slice_count(" ") > 1 ? doc_comment.get_slice(" ", 1) : String();
add_color_region(beg, end, doc_comment_color, end.is_empty());
}

/* Strings */
string_color = EDITOR_GET("text_editor/theme/highlighting/string_color");
List<String> strings;
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,7 @@ class GDScriptLanguage : public ScriptLanguage {
virtual void get_reserved_words(List<String> *p_words) const override;
virtual bool is_control_flow_keyword(String p_keywords) const override;
virtual void get_comment_delimiters(List<String> *p_delimiters) const override;
virtual void get_doc_comment_delimiters(List<String> *p_delimiters) const override;
virtual void get_string_delimiters(List<String> *p_delimiters) const override;
virtual bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
Expand Down
4 changes: 4 additions & 0 deletions modules/gdscript/gdscript_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ void GDScriptLanguage::get_comment_delimiters(List<String> *p_delimiters) const
p_delimiters->push_back("#");
}

void GDScriptLanguage::get_doc_comment_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("##");
}

void GDScriptLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("\" \"");
p_delimiters->push_back("' '");
Expand Down
5 changes: 5 additions & 0 deletions modules/mono/csharp_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,11 @@ void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("/* */"); // delimited comment
}

void CSharpLanguage::get_doc_comment_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("///"); // single-line doc comment
p_delimiters->push_back("/** */"); // delimited doc comment
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const {
p_delimiters->push_back("' '"); // character literal
p_delimiters->push_back("\" \""); // regular string literal
Expand Down
1 change: 1 addition & 0 deletions modules/mono/csharp_script.h
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ class CSharpLanguage : public ScriptLanguage {
void get_reserved_words(List<String> *p_words) const override;
bool is_control_flow_keyword(String p_keyword) const override;
void get_comment_delimiters(List<String> *p_delimiters) const override;
void get_doc_comment_delimiters(List<String> *p_delimiters) const override;
void get_string_delimiters(List<String> *p_delimiters) const override;
bool is_using_templates() override;
virtual Ref<Script> make_template(const String &p_template, const String &p_class_name, const String &p_base_class_name) const override;
Expand Down
Loading