summaryrefslogtreecommitdiff
path: root/modules/gdscript
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript')
-rw-r--r--modules/gdscript/gd_compiler.cpp2
-rw-r--r--modules/gdscript/gd_editor.cpp84
-rw-r--r--modules/gdscript/gd_function.cpp24
-rw-r--r--modules/gdscript/gd_function.h2
-rw-r--r--modules/gdscript/gd_parser.cpp28
-rw-r--r--modules/gdscript/gd_parser.h4
-rw-r--r--modules/gdscript/gd_script.cpp6
-rw-r--r--modules/gdscript/gd_script.h2
-rw-r--r--modules/gdscript/gd_tokenizer.cpp4
-rw-r--r--modules/gdscript/gd_tokenizer.h1
10 files changed, 68 insertions, 89 deletions
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index 12b43d6060..d4ede4cb17 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -1014,7 +1014,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
}
} break;
- case GDParser::OperatorNode::OP_EXTENDS: {
+ case GDParser::OperatorNode::OP_IS: {
ERR_FAIL_COND_V(on->arguments.size() != 2, false);
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index 4667e541dd..5e3ce31dd6 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -69,6 +69,19 @@ Ref<Script> GDScriptLanguage::get_template(const String &p_class_name, const Str
return script;
}
+bool GDScriptLanguage::is_using_templates() {
+
+ return true;
+}
+
+void GDScriptLanguage::make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script) {
+
+ String src = p_script->get_source_code();
+ src = src.replace("%BASE%", p_base_class_name);
+ src = src.replace("%TS%", _get_indentation());
+ p_script->set_source_code(src);
+}
+
bool GDScriptLanguage::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 {
GDParser parser;
@@ -1321,7 +1334,7 @@ static void _find_identifiers(GDCompletionContext &context, int p_line, bool p_o
static const char *_type_names[Variant::VARIANT_MAX] = {
"null", "bool", "int", "float", "String", "Vector2", "Rect2", "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform",
- "Color", "Image", "NodePath", "RID", "Object", "InputEvent", "Dictionary", "Array", "RawArray", "IntArray", "FloatArray", "StringArray",
+ "Color", "NodePath", "RID", "Object", "Dictionary", "Array", "RawArray", "IntArray", "FloatArray", "StringArray",
"Vector2Array", "Vector3Array", "ColorArray"
};
@@ -1425,22 +1438,7 @@ void get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_lis
static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, String &arghint) {
//print_line("find type arguments?");
- if (id.type == Variant::INPUT_EVENT && String(p_method) == "is_action" && p_argidx == 0) {
-
- List<PropertyInfo> pinfo;
- GlobalConfig::get_singleton()->get_property_list(&pinfo);
-
- for (List<PropertyInfo>::Element *E = pinfo.front(); E; E = E->next()) {
- const PropertyInfo &pi = E->get();
-
- if (!pi.name.begins_with("input/"))
- continue;
-
- String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length());
- result.insert("\"" + name + "\"");
- }
-
- } else if (id.type == Variant::OBJECT && id.obj_type != StringName()) {
+ if (id.type == Variant::OBJECT && id.obj_type != StringName()) {
MethodBind *m = ClassDB::get_method(id.obj_type, p_method);
if (!m) {
@@ -2266,54 +2264,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
} else {
- if (t.type == Variant::INPUT_EVENT) {
-
- //this is hardcoded otherwise it's not obvious
- Set<String> exclude;
-
- for (int i = 0; i < InputEvent::TYPE_MAX; i++) {
-
- InputEvent ie;
- ie.type = InputEvent::Type(i);
- static const char *evnames[] = {
- "# Common",
- "# Key",
- "# MouseMotion",
- "# MouseButton",
- "# JoypadMotion",
- "# JoypadButton",
- "# ScreenTouch",
- "# ScreenDrag",
- "# Action"
- };
-
- r_options->push_back(evnames[i]);
-
- Variant v = ie;
-
- if (i == 0) {
- List<MethodInfo> mi;
- v.get_method_list(&mi);
- for (List<MethodInfo>::Element *E = mi.front(); E; E = E->next()) {
- r_options->push_back(E->get().name + "(");
- }
- }
-
- List<PropertyInfo> pi;
- v.get_property_list(&pi);
-
- for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
-
- if (i == 0)
- exclude.insert(E->get().name);
- else if (exclude.has(E->get().name))
- continue;
-
- r_options->push_back(E->get().name);
- }
- }
- return OK;
- } else {
+ //check InputEvent hint
+ {
if (t.value.get_type() == Variant::NIL) {
Variant::CallError ce;
t.value = Variant::construct(t.type, NULL, 0, ce);
@@ -2395,7 +2347,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
}
} break;
- case GDParser::COMPLETION_PRELOAD: {
+ case GDParser::COMPLETION_RESOURCE_PATH: {
if (EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))
get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), options);
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index 608256c88a..e8a8e20927 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -358,12 +358,12 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
- err_text = "Left operand of 'extends' is not an instance of anything.";
+ err_text = "Left operand of 'is' is not an instance of anything.";
break;
}
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
- err_text = "Right operand of 'extends' is not a class.";
+ err_text = "Right operand of 'is' is not a class.";
break;
}
#endif
@@ -401,7 +401,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (!nc) {
- err_text = "Right operand of 'extends' is not a class (type: '" + obj_B->get_class() + "').";
+ err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
break;
}
@@ -1433,9 +1433,21 @@ Variant GDFunctionState::_signal_callback(const Variant **p_args, int p_argcount
return ret;
}
-bool GDFunctionState::is_valid() const {
+bool GDFunctionState::is_valid(bool p_extended_check) const {
- return function != NULL;
+ if (function == NULL)
+ return false;
+
+ if (p_extended_check) {
+ //class instance gone?
+ if (state.instance_id && !ObjectDB::get_instance(state.instance_id))
+ return false;
+ //script gone?
+ if (state.script_id && !ObjectDB::get_instance(state.script_id))
+ return false;
+ }
+
+ return true;
}
Variant GDFunctionState::resume(const Variant &p_arg) {
@@ -1464,7 +1476,7 @@ Variant GDFunctionState::resume(const Variant &p_arg) {
void GDFunctionState::_bind_methods() {
ClassDB::bind_method(D_METHOD("resume:Variant", "arg"), &GDFunctionState::resume, DEFVAL(Variant()));
- ClassDB::bind_method(D_METHOD("is_valid"), &GDFunctionState::is_valid);
+ ClassDB::bind_method(D_METHOD("is_valid", "extended_check"), &GDFunctionState::is_valid, DEFVAL(false));
ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "_signal_callback", &GDFunctionState::_signal_callback, MethodInfo("_signal_callback"));
}
diff --git a/modules/gdscript/gd_function.h b/modules/gdscript/gd_function.h
index f0bf33147b..6d20b19777 100644
--- a/modules/gdscript/gd_function.h
+++ b/modules/gdscript/gd_function.h
@@ -237,7 +237,7 @@ protected:
static void _bind_methods();
public:
- bool is_valid() const;
+ bool is_valid(bool p_extended_check = false) const;
Variant resume(const Variant &p_arg = Variant());
GDFunctionState();
~GDFunctionState();
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index b02d7f713b..d64cd86de6 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -387,15 +387,21 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
_set_error("Expected '(' after 'preload'");
return NULL;
}
- completion_cursor = StringName();
- completion_type = COMPLETION_PRELOAD;
- completion_class = current_class;
- completion_function = current_function;
- completion_line = tokenizer->get_token_line();
- completion_block = current_block;
- completion_found = true;
tokenizer->advance();
+ if (tokenizer->get_token() == GDTokenizer::TK_CURSOR) {
+ completion_cursor = StringName();
+ completion_node = p_parent;
+ completion_type = COMPLETION_RESOURCE_PATH;
+ completion_class = current_class;
+ completion_function = current_function;
+ completion_line = tokenizer->get_token_line();
+ completion_block = current_block;
+ completion_argument = 0;
+ completion_found = true;
+ tokenizer->advance();
+ }
+
String path;
bool found_constant = false;
bool valid = false;
@@ -467,10 +473,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
_set_error("Expected ')' after 'preload' path");
return NULL;
}
+ tokenizer->advance();
ConstantNode *constant = alloc_node<ConstantNode>();
constant->value = res;
- tokenizer->advance();
expr = constant;
} else if (tokenizer->get_token() == GDTokenizer::TK_PR_YIELD) {
@@ -1071,7 +1077,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
case GDTokenizer::TK_OP_BIT_AND: op = OperatorNode::OP_BIT_AND; break;
case GDTokenizer::TK_OP_BIT_OR: op = OperatorNode::OP_BIT_OR; break;
case GDTokenizer::TK_OP_BIT_XOR: op = OperatorNode::OP_BIT_XOR; break;
- case GDTokenizer::TK_PR_EXTENDS: op = OperatorNode::OP_EXTENDS; break;
+ case GDTokenizer::TK_PR_IS: op = OperatorNode::OP_IS; break;
case GDTokenizer::TK_CF_IF: op = OperatorNode::OP_TERNARY_IF; break;
case GDTokenizer::TK_CF_ELSE: op = OperatorNode::OP_TERNARY_ELSE; break;
default: valid = false; break;
@@ -1111,7 +1117,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
switch (expression[i].op) {
- case OperatorNode::OP_EXTENDS:
+ case OperatorNode::OP_IS:
priority = -1;
break; //before anything
@@ -1414,7 +1420,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
}
}
- if (op->op == OperatorNode::OP_EXTENDS) {
+ if (op->op == OperatorNode::OP_IS) {
//nothing much
return op;
}
diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h
index 4f3ca0dc5f..3ad3466624 100644
--- a/modules/gdscript/gd_parser.h
+++ b/modules/gdscript/gd_parser.h
@@ -216,7 +216,7 @@ public:
OP_CALL,
OP_PARENT_CALL,
OP_YIELD,
- OP_EXTENDS,
+ OP_IS,
//indexing operator
OP_INDEX,
OP_INDEX_NAMED,
@@ -437,7 +437,7 @@ public:
COMPLETION_PARENT_FUNCTION,
COMPLETION_METHOD,
COMPLETION_CALL_ARGUMENTS,
- COMPLETION_PRELOAD,
+ COMPLETION_RESOURCE_PATH,
COMPLETION_INDEX,
COMPLETION_VIRTUAL_FUNC,
COMPLETION_YIELD,
diff --git a/modules/gdscript/gd_script.cpp b/modules/gdscript/gd_script.cpp
index 173014b138..1dcc442234 100644
--- a/modules/gdscript/gd_script.cpp
+++ b/modules/gdscript/gd_script.cpp
@@ -615,6 +615,11 @@ Error GDScript::reload(bool p_keep_state) {
if (basedir != "")
basedir = basedir.get_base_dir();
+ if (basedir.find("res://") == -1 && basedir.find("user://") == -1) {
+ //loading a template, don't parse
+ return OK;
+ }
+
valid = false;
GDParser parser;
Error err = parser.parse(source, basedir, false, path);
@@ -1812,6 +1817,7 @@ void GDScriptLanguage::get_reserved_words(List<String> *p_words) const {
"breakpoint",
"class",
"extends",
+ "is",
"func",
"preload",
"setget",
diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h
index 00ae136790..ebef4fed74 100644
--- a/modules/gdscript/gd_script.h
+++ b/modules/gdscript/gd_script.h
@@ -381,6 +381,8 @@ public:
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 is_using_templates();
+ virtual void make_template(const String &p_class_name, const String &p_base_class_name, Ref<Script> &p_script);
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 Script *create_script() const;
virtual bool has_named_classes() const;
diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp
index 13674f1f9a..f4e0cc8e29 100644
--- a/modules/gdscript/gd_tokenizer.cpp
+++ b/modules/gdscript/gd_tokenizer.cpp
@@ -90,6 +90,7 @@ const char *GDTokenizer::token_names[TK_MAX] = {
"func",
"class",
"extends",
+ "is",
"onready",
"tool",
"static",
@@ -800,10 +801,8 @@ void GDTokenizerText::_advance() {
{ Variant::BASIS, "Basis" },
{ Variant::TRANSFORM, "Transform" },
{ Variant::COLOR, "Color" },
- { Variant::IMAGE, "Image" },
{ Variant::_RID, "RID" },
{ Variant::OBJECT, "Object" },
- { Variant::INPUT_EVENT, "InputEvent" },
{ Variant::NODE_PATH, "NodePath" },
{ Variant::DICTIONARY, "Dictionary" },
{ Variant::ARRAY, "Array" },
@@ -866,6 +865,7 @@ void GDTokenizerText::_advance() {
{ TK_PR_FUNCTION, "func" },
{ TK_PR_CLASS, "class" },
{ TK_PR_EXTENDS, "extends" },
+ { TK_PR_IS, "is" },
{ TK_PR_ONREADY, "onready" },
{ TK_PR_TOOL, "tool" },
{ TK_PR_STATIC, "static" },
diff --git a/modules/gdscript/gd_tokenizer.h b/modules/gdscript/gd_tokenizer.h
index ea7629b661..c051176097 100644
--- a/modules/gdscript/gd_tokenizer.h
+++ b/modules/gdscript/gd_tokenizer.h
@@ -96,6 +96,7 @@ public:
TK_PR_FUNCTION,
TK_PR_CLASS,
TK_PR_EXTENDS,
+ TK_PR_IS,
TK_PR_ONREADY,
TK_PR_TOOL,
TK_PR_STATIC,