diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 1848cbf6be0..2e4a4c40dd5 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -37,6 +37,7 @@ #include "os/file_access.h" #ifdef TOOLS_ENABLED +#include "core/reference.h" #include "editor/editor_file_system.h" #include "editor/editor_settings.h" #include "engine.h" @@ -464,75 +465,10 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na return s; } +//////// COMPLETION ////////// + #if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED) -struct GDScriptCompletionIdentifier { - - String enumeration; - StringName obj_type; - Ref script; - Variant::Type type; - Variant value; //im case there is a value, also return it - - GDScriptCompletionIdentifier() : - type(Variant::NIL) {} -}; - -static GDScriptCompletionIdentifier _get_type_from_variant(const Variant &p_variant, bool p_allow_gdnative_class = false) { - - GDScriptCompletionIdentifier t; - t.type = p_variant.get_type(); - t.value = p_variant; - if (p_variant.get_type() == Variant::OBJECT) { - Object *obj = p_variant; - if (obj) { - - if (p_allow_gdnative_class && Object::cast_to(obj)) { - t.obj_type = Object::cast_to(obj)->get_name(); - t.value = Variant(); - } else { - - t.obj_type = obj->get_class(); - } - } - } - return t; -} - -static GDScriptCompletionIdentifier _get_type_from_pinfo(const PropertyInfo &p_info) { - - GDScriptCompletionIdentifier t; - t.type = p_info.type; - if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { - t.obj_type = p_info.hint_string; - } - return t; -} - -static bool _get_type_from_parser_type(const GDScriptParser::DataType &p_datatype, GDScriptCompletionIdentifier &r_type) { - if (p_datatype.has_type && p_datatype.kind != GDScriptParser::DataType::UNRESOLVED) { - switch (p_datatype.kind) { - case GDScriptParser::DataType::BUILTIN: { - r_type.type = p_datatype.builtin_type; - return true; - } break; - case GDScriptParser::DataType::NATIVE: { - r_type.type = Variant::OBJECT; - r_type.obj_type = p_datatype.native_type; - return true; - } break; - case GDScriptParser::DataType::SCRIPT: - case GDScriptParser::DataType::GDSCRIPT: { - r_type.type = Variant::OBJECT; - r_type.script = p_datatype.script_type; - r_type.obj_type = r_type.script->get_instance_base_type(); - return true; - } break; - } - } - return false; -} - struct GDScriptCompletionContext { const GDScriptParser::ClassNode *_class; @@ -540,1062 +476,1612 @@ struct GDScriptCompletionContext { const GDScriptParser::BlockNode *block; Object *base; String base_path; + int line; + + GDScriptCompletionContext() : + _class(NULL), + function(NULL), + block(NULL), + base(NULL) {} }; -static Ref _get_parent_class(GDScriptCompletionContext &context) { +struct GDScriptCompletionIdentifier { + GDScriptParser::DataType type; + String enumeration; + Variant value; + const GDScriptParser::Node *assigned_expression; - if (context._class->extends_used) { - //do inheritance - String path = context._class->extends_file; + GDScriptCompletionIdentifier() : + assigned_expression(NULL) {} +}; - Ref script; - Ref native; +static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Set &r_list) { - if (path != "") { - //path (and optionally subclasses) + for (int i = 0; i < p_dir->get_file_count(); i++) { + r_list.insert("\"" + p_dir->get_file_path(i) + "\""); + } - if (path.is_rel_path()) { + for (int i = 0; i < p_dir->get_subdir_count(); i++) { + _get_directory_contents(p_dir->get_subdir(i), r_list); + } +} - path = context.base_path.plus_file(path); - } +static String _get_visual_datatype(const PropertyInfo &p_info, bool p_isarg = true) { - if (ScriptCodeCompletionCache::get_singleton()) - script = ScriptCodeCompletionCache::get_singleton()->get_cached_resource(path); - else - script = ResourceLoader::load(path); + if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + String enum_name = p_info.class_name; + if (enum_name.find(".") == -1) { + return enum_name; + } + return enum_name.get_slice(".", 1); + } - if (script.is_null()) { - return REF(); - } - if (!script->is_valid()) { - - return REF(); - } - //print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid)); - - if (context._class->extends_class.size()) { - - for (int i = 0; i < context._class->extends_class.size(); i++) { - - String sub = context._class->extends_class[i]; - if (script->get_subclasses().has(sub)) { - - script = script->get_subclasses()[sub]; - } else { - - return REF(); - } - } - } - - if (script.is_valid()) - return script; + String n = p_info.name; + int idx = n.find(":"); + if (idx != -1) { + return n.substr(idx + 1, n.length()); + } + if (p_info.type == Variant::OBJECT) { + if (p_info.hint == PROPERTY_HINT_RESOURCE_TYPE) { + return p_info.hint_string; } else { - - if (context._class->extends_class.size() == 0) { - ERR_PRINT("BUG"); - return REF(); - } - - String base = context._class->extends_class[0]; - - if (context._class->extends_class.size() > 1) { - - return REF(); - } - //if not found, try engine classes - if (!GDScriptLanguage::get_singleton()->get_global_map().has(base)) { - - return REF(); - } - - int base_idx = GDScriptLanguage::get_singleton()->get_global_map()[base]; - native = GDScriptLanguage::get_singleton()->get_global_array()[base_idx]; - return native; + return p_info.class_name.operator String(); + } + } + if (p_info.type == Variant::NIL) { + if (p_isarg || (p_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT)) { + return "var"; + } else { + return "void"; } } - return Ref(); + return Variant::get_type_name(p_info.type); } -static GDScriptCompletionIdentifier _get_native_class(GDScriptCompletionContext &context) { +static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value) { + GDScriptCompletionIdentifier ci; + ci.value = p_value; + ci.type.is_constant = true; + ci.type.has_type = true; + ci.type.kind = GDScriptParser::DataType::BUILTIN; + ci.type.builtin_type = p_value.get_type(); - GDScriptCompletionIdentifier id; - - REF pc = _get_parent_class(context); - if (!pc.is_valid()) { - return id; - } - Ref nc = pc; - Ref s = pc; - - if (s.is_null() && nc.is_null()) { - return id; - } - while (!s.is_null()) { - nc = s->get_native(); - s = s->get_base(); - } - if (nc.is_null()) { - return id; + if (ci.type.builtin_type == Variant::OBJECT) { + Object *obj = p_value.operator Object *(); + if (!obj) { + return ci; + } + ci.type.native_type = obj->get_class_name(); + Ref