Skip to content

Commit

Permalink
Merge pull request #19264 from vnen/typed-gdscript-final
Browse files Browse the repository at this point in the history
Typed GDScript
  • Loading branch information
akien-mga authored Jul 21, 2018
2 parents 2b9902d + 3e87ad5 commit 9241536
Show file tree
Hide file tree
Showing 30 changed files with 6,654 additions and 2,662 deletions.
2 changes: 1 addition & 1 deletion core/script_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class ScriptLanguage {
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const = 0;
virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {}
virtual bool is_using_templates() { return false; }
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const = 0;
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, Set<int> *r_safe_lines = NULL) const = 0;
virtual String validate_path(const String &p_path) const { return ""; }
virtual Script *create_script() const = 0;
virtual bool has_named_classes() const = 0;
Expand Down
4 changes: 3 additions & 1 deletion editor/connections_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -820,7 +820,9 @@ void ConnectionsDock::update_tree() {
if (i > 0)
signaldesc += ", ";
String tname = "var";
if (pi.type != Variant::NIL) {
if (pi.type == Variant::OBJECT && pi.class_name != StringName()) {
tname = pi.class_name.operator String();
} else if (pi.type != Variant::NIL) {
tname = Variant::get_type_name(pi.type);
}
signaldesc += tname + " " + (pi.name == "" ? String("arg " + itos(i)) : pi.name);
Expand Down
3 changes: 3 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {

_initial_set("text_editor/highlighting/highlight_all_occurrences", true);
_initial_set("text_editor/highlighting/highlight_current_line", true);
_initial_set("text_editor/highlighting/highlight_type_safe_lines", true);
_initial_set("text_editor/cursor/scroll_past_end_of_file", false);

_initial_set("text_editor/indent/type", 0);
Expand Down Expand Up @@ -404,6 +405,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("text_editor/completion/callhint_tooltip_offset", Vector2());
_initial_set("text_editor/files/restore_scripts_on_load", true);
_initial_set("text_editor/completion/complete_file_paths", true);
_initial_set("text_editor/completion/add_type_hints", false);

_initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
_initial_set("docks/scene_tree/draw_relationship_lines", false);
Expand Down Expand Up @@ -592,6 +594,7 @@ void EditorSettings::_load_default_text_editor_theme() {
_initial_set("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
_initial_set("text_editor/highlighting/text_color", Color::html("aaaaaa"));
_initial_set("text_editor/highlighting/line_number_color", Color::html("66aaaaaa"));
_initial_set("text_editor/highlighting/safe_line_number_color", Color::html("99aac8aa"));
_initial_set("text_editor/highlighting/caret_color", Color::html("aaaaaa"));
_initial_set("text_editor/highlighting/caret_background_color", Color::html("000000"));
_initial_set("text_editor/highlighting/text_selected_color", Color::html("000000"));
Expand Down
2 changes: 2 additions & 0 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color completion_font_color = font_color;
const Color text_color = font_color;
const Color line_number_color = dim_color;
const Color safe_line_number_color = dim_color * Color(1, 1.2, 1, 1.5);
const Color caret_color = mono_color;
const Color caret_background_color = mono_color.inverted();
const Color text_selected_color = dark_color_3;
Expand Down Expand Up @@ -1123,6 +1124,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
setting->set_initial_value("text_editor/highlighting/completion_font_color", completion_font_color, true);
setting->set_initial_value("text_editor/highlighting/text_color", text_color, true);
setting->set_initial_value("text_editor/highlighting/line_number_color", line_number_color, true);
setting->set_initial_value("text_editor/highlighting/safe_line_number_color", safe_line_number_color, true);
setting->set_initial_value("text_editor/highlighting/caret_color", caret_color, true);
setting->set_initial_value("text_editor/highlighting/caret_background_color", caret_background_color, true);
setting->set_initial_value("text_editor/highlighting/text_selected_color", text_selected_color, true);
Expand Down
21 changes: 20 additions & 1 deletion editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ void ScriptTextEditor::_load_theme_settings() {
Color completion_font_color = EDITOR_GET("text_editor/highlighting/completion_font_color");
Color text_color = EDITOR_GET("text_editor/highlighting/text_color");
Color line_number_color = EDITOR_GET("text_editor/highlighting/line_number_color");
Color safe_line_number_color = EDITOR_GET("text_editor/highlighting/safe_line_number_color");
Color caret_color = EDITOR_GET("text_editor/highlighting/caret_color");
Color caret_background_color = EDITOR_GET("text_editor/highlighting/caret_background_color");
Color text_selected_color = EDITOR_GET("text_editor/highlighting/text_selected_color");
Expand Down Expand Up @@ -147,6 +148,7 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->add_color_override("completion_font_color", completion_font_color);
text_edit->add_color_override("font_color", text_color);
text_edit->add_color_override("line_number_color", line_number_color);
text_edit->add_color_override("safe_line_number_color", safe_line_number_color);
text_edit->add_color_override("caret_color", caret_color);
text_edit->add_color_override("caret_background_color", caret_background_color);
text_edit->add_color_override("font_selected_color", text_selected_color);
Expand Down Expand Up @@ -589,6 +591,7 @@ void ScriptTextEditor::set_edited_script(const Ref<Script> &p_script) {

emit_signal("name_changed");
code_editor->update_line_and_column();
call_deferred("_validate_script");
}

void ScriptTextEditor::_validate_script() {
Expand All @@ -599,8 +602,9 @@ void ScriptTextEditor::_validate_script() {

String text = te->get_text();
List<String> fnc;
Set<int> safe_lines;

if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc)) {
if (!script->get_language()->validate(text, line, col, errortxt, script->get_path(), &fnc, &safe_lines)) {
String error_text = "error(" + itos(line) + "," + itos(col) + "): " + errortxt;
code_editor->set_error(error_text);
} else {
Expand All @@ -621,8 +625,23 @@ void ScriptTextEditor::_validate_script() {
}

line--;
bool highlight_safe = EDITOR_DEF("text_editor/highlighting/highlight_type_safe_lines", true);
bool last_is_safe = false;
for (int i = 0; i < te->get_line_count(); i++) {
te->set_line_as_marked(i, line == i);
if (highlight_safe) {
if (safe_lines.has(i + 1)) {
te->set_line_as_safe(i, true);
last_is_safe = true;
} else if (last_is_safe && (te->is_line_comment(i) || te->get_line(i).strip_edges().empty())) {
te->set_line_as_safe(i, true);
} else {
te->set_line_as_safe(i, false);
last_is_safe = false;
}
} else {
te->set_line_as_safe(i, false);
}
}

emit_signal("name_changed");
Expand Down
15 changes: 3 additions & 12 deletions main/tests/test_gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,6 @@ static String _parser_expr(const GDScriptParser::Node *p_expr) {
case GDScriptParser::OperatorNode::OP_BIT_INVERT: {
txt = "~" + _parser_expr(c_node->arguments[0]);
} break;
case GDScriptParser::OperatorNode::OP_PREINC: {
} break;
case GDScriptParser::OperatorNode::OP_PREDEC: {
} break;
case GDScriptParser::OperatorNode::OP_INC: {
} break;
case GDScriptParser::OperatorNode::OP_DEC: {
} break;
case GDScriptParser::OperatorNode::OP_IN: {
txt = _parser_expr(c_node->arguments[0]) + " in " + _parser_expr(c_node->arguments[1]);
} break;
Expand Down Expand Up @@ -455,10 +447,9 @@ static void _parser_show_class(const GDScriptParser::ClassNode *p_class, int p_i
print_line("\n");
}

for (int i = 0; i < p_class->constant_expressions.size(); i++) {

const GDScriptParser::ClassNode::Constant &constant = p_class->constant_expressions[i];
_print_indent(p_indent, "const " + String(constant.identifier) + "=" + _parser_expr(constant.expression));
for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) {
const GDScriptParser::ClassNode::Constant &constant = E->get();
_print_indent(p_indent, "const " + String(E->key()) + "=" + _parser_expr(constant.expression));
}

for (int i = 0; i < p_class->variables.size(); i++) {
Expand Down
2 changes: 1 addition & 1 deletion modules/gdnative/nativescript/nativescript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ Ref<Script> NativeScriptLanguage::get_template(const String &p_class_name, const
s->set_class_name(p_class_name);
return Ref<NativeScript>(s);
}
bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const {
bool NativeScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, Set<int> *r_safe_lines) const {
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion modules/gdnative/nativescript/nativescript.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ class NativeScriptLanguage : public ScriptLanguage {
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const;
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, Set<int> *r_safe_lines = NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
virtual bool supports_builtin_mode() const;
Expand Down
2 changes: 1 addition & 1 deletion modules/gdnative/pluginscript/pluginscript_language.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Ref<Script> PluginScriptLanguage::get_template(const String &p_class_name, const
return script;
}

bool PluginScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const {
bool PluginScriptLanguage::validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions, Set<int> *r_safe_lines) const {
PoolStringArray functions;
if (_desc.validate) {
bool ret = _desc.validate(
Expand Down
2 changes: 1 addition & 1 deletion modules/gdnative/pluginscript/pluginscript_language.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class PluginScriptLanguage : public ScriptLanguage {
virtual void get_comment_delimiters(List<String> *p_delimiters) const;
virtual void get_string_delimiters(List<String> *p_delimiters) const;
virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL) const;
virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path = "", List<String> *r_functions = NULL, Set<int> *r_safe_lines = NULL) const;
virtual Script *create_script() const;
virtual bool has_named_classes() const;
virtual bool supports_builtin_mode() const;
Expand Down
30 changes: 30 additions & 0 deletions modules/gdscript/editor/gdscript_highlighter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,11 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
bool in_keyword = false;
bool in_word = false;
bool in_function_name = false;
bool in_variable_declaration = false;
bool in_member_variable = false;
bool in_node_path = false;
bool is_hex_notation = false;
bool expect_type = false;
Color keyword_color;
Color color;

Expand Down Expand Up @@ -205,6 +207,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_

if (str[k] == '(') {
in_function_name = true;
} else if (previous_text == GDScriptTokenizer::get_token_name(GDScriptTokenizer::TK_PR_VAR)) {
in_variable_declaration = true;
}
}

Expand All @@ -222,6 +226,28 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
if (is_symbol) {
in_function_name = false;
in_member_variable = false;

if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') {
expect_type = false;
}
if (j > 0 && str[j] == '>' && str[j - 1] == '-') {
expect_type = true;
}

if (in_variable_declaration || previous_text == "(" || previous_text == ",") {
int k = j;
// Skip space
while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) {
k++;
}

if (str[k] == ':') {
// has type hint
expect_type = true;
}
}

in_variable_declaration = false;
}

if (!in_node_path && in_region == -1 && str[j] == '$') {
Expand Down Expand Up @@ -256,6 +282,9 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_
} else if (is_number) {
next_type = NUMBER;
color = number_color;
} else if (expect_type) {
next_type = TYPE;
color = type_color;
} else {
next_type = IDENTIFIER;
}
Expand Down Expand Up @@ -330,6 +359,7 @@ void GDScriptSyntaxHighlighter::_update_cache() {

function_definition_color = EDITOR_GET("text_editor/highlighting/gdscript/function_definition_color");
node_path_color = EDITOR_GET("text_editor/highlighting/gdscript/node_path_color");
type_color = EDITOR_GET("text_editor/highlighting/base_type_color");
}

SyntaxHighlighter *GDScriptSyntaxHighlighter::create() {
Expand Down
4 changes: 3 additions & 1 deletion modules/gdscript/editor/gdscript_highlighter.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class GDScriptSyntaxHighlighter : public SyntaxHighlighter {
FUNCTION,
KEYWORD,
MEMBER,
IDENTIFIER
IDENTIFIER,
TYPE,
};

// colours
Expand All @@ -56,6 +57,7 @@ class GDScriptSyntaxHighlighter : public SyntaxHighlighter {
Color number_color;
Color member_color;
Color node_path_color;
Color type_color;

public:
static SyntaxHighlighter *create();
Expand Down
64 changes: 49 additions & 15 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,16 +220,14 @@ void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
void GDScript::get_script_method_list(List<MethodInfo> *p_list) const {

for (const Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) {
GDScriptFunction *func = E->get();
MethodInfo mi;
mi.name = E->key();
for (int i = 0; i < E->get()->get_argument_count(); i++) {
PropertyInfo arg;
arg.type = Variant::NIL; //variant
arg.name = E->get()->get_argument_name(i);
mi.arguments.push_back(arg);
for (int i = 0; i < func->get_argument_count(); i++) {
mi.arguments.push_back(func->get_argument_type(i));
}

mi.return_val.name = "Variant";
mi.return_val = func->get_return_type();
p_list->push_back(mi);
}
}
Expand Down Expand Up @@ -277,16 +275,14 @@ MethodInfo GDScript::get_method_info(const StringName &p_method) const {
if (!E)
return MethodInfo();

GDScriptFunction *func = E->get();
MethodInfo mi;
mi.name = E->key();
for (int i = 0; i < E->get()->get_argument_count(); i++) {
PropertyInfo arg;
arg.type = Variant::NIL; //variant
arg.name = E->get()->get_argument_name(i);
mi.arguments.push_back(arg);
for (int i = 0; i < func->get_argument_count(); i++) {
mi.arguments.push_back(func->get_argument_type(i));
}

mi.return_val.name = "Variant";
mi.return_val = func->get_return_type();
return mi;
}

Expand Down Expand Up @@ -941,8 +937,12 @@ bool GDScriptInstance::set(const StringName &p_name, const Variant &p_value) {
if (err.error == Variant::CallError::CALL_OK) {
return true; //function exists, call was successful
}
} else
} else {
if (!E->get().data_type.is_type(p_value)) {
return false; // Type mismatch
}
members[E->get().index] = p_value;
}
return true;
}
}
Expand Down Expand Up @@ -1735,7 +1735,9 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"NAN",
"self",
"true",
"void",
// functions
"as",
"assert",
"breakpoint",
"class",
Expand Down Expand Up @@ -1824,8 +1826,40 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
if (parser.get_parse_tree() && parser.get_parse_tree()->type == GDScriptParser::Node::TYPE_CLASS) {

const GDScriptParser::ClassNode *c = static_cast<const GDScriptParser::ClassNode *>(parser.get_parse_tree());
if (r_base_type && c->extends_used && c->extends_class.size() == 1) {
*r_base_type = c->extends_class[0]; //todo, should work much better
if (r_base_type) {
GDScriptParser::DataType base_type;
if (c->base_type.has_type) {
base_type = c->base_type;
while (base_type.has_type && base_type.kind != GDScriptParser::DataType::NATIVE) {
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
base_type = base_type.class_type->base_type;
} break;
case GDScriptParser::DataType::GDSCRIPT: {
Ref<GDScript> gds = base_type.script_type;
if (gds.is_valid()) {
base_type.kind = GDScriptParser::DataType::NATIVE;
base_type.native_type = gds->get_instance_base_type();
} else {
base_type = GDScriptParser::DataType();
}
} break;
default: {
base_type = GDScriptParser::DataType();
} break;
}
}
}
if (base_type.has_type) {
*r_base_type = base_type.native_type;
} else {
// Fallback
if (c->extends_used && c->extends_class.size() == 1) {
*r_base_type = c->extends_class[0];
} else if (!c->extends_used) {
*r_base_type = "Reference";
}
}
}
return c->name;
}
Expand Down
Loading

0 comments on commit 9241536

Please sign in to comment.