Implement CSharpScript::get_script_method_list and related functionality.
This commit is contained in:
parent
41d1dba35f
commit
f13f2d512f
7 changed files with 103 additions and 2 deletions
|
@ -210,6 +210,9 @@ void PropertySelector::_update_search() {
|
||||||
|
|
||||||
methods.push_back(MethodInfo("*Script Methods"));
|
methods.push_back(MethodInfo("*Script Methods"));
|
||||||
Object::cast_to<Script>(obj)->get_script_method_list(&methods);
|
Object::cast_to<Script>(obj)->get_script_method_list(&methods);
|
||||||
|
// TODO: Filter out things unsuitable for explicit calls, like constructors.
|
||||||
|
|
||||||
|
// TODO: We should handle script class hierarchies somehow. Right now we don't; it's unclear where this functionality should live.
|
||||||
}
|
}
|
||||||
|
|
||||||
StringName base = base_type;
|
StringName base = base_type;
|
||||||
|
|
|
@ -2474,6 +2474,17 @@ void CSharpScript::set_source_code(const String &p_code) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSharpScript::get_script_method_list(List<MethodInfo> *p_list) const {
|
||||||
|
|
||||||
|
if (!script_class)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Vector<GDMonoMethod *> &methods = script_class->get_all_methods();
|
||||||
|
for (int i = 0; i < methods.size(); ++i) {
|
||||||
|
p_list->push_back(methods[i]->get_method_info());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CSharpScript::has_method(const StringName &p_method) const {
|
bool CSharpScript::has_method(const StringName &p_method) const {
|
||||||
|
|
||||||
if (!script_class)
|
if (!script_class)
|
||||||
|
@ -2482,6 +2493,25 @@ bool CSharpScript::has_method(const StringName &p_method) const {
|
||||||
return script_class->has_fetched_method_unknown_params(p_method);
|
return script_class->has_fetched_method_unknown_params(p_method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MethodInfo CSharpScript::get_method_info(const StringName &p_method) const {
|
||||||
|
|
||||||
|
if (!script_class)
|
||||||
|
return MethodInfo();
|
||||||
|
|
||||||
|
GDMonoClass *top = script_class;
|
||||||
|
|
||||||
|
while (top && top != native) {
|
||||||
|
GDMonoMethod *params = top->get_fetched_method_unknown_params(p_method);
|
||||||
|
if (params) {
|
||||||
|
return params->get_method_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
top = top->get_parent_class();
|
||||||
|
}
|
||||||
|
|
||||||
|
return MethodInfo();
|
||||||
|
}
|
||||||
|
|
||||||
Error CSharpScript::reload(bool p_keep_state) {
|
Error CSharpScript::reload(bool p_keep_state) {
|
||||||
|
|
||||||
bool has_instances;
|
bool has_instances;
|
||||||
|
|
|
@ -174,9 +174,9 @@ public:
|
||||||
virtual Ref<Script> get_base_script() const;
|
virtual Ref<Script> get_base_script() const;
|
||||||
virtual ScriptLanguage *get_language() const;
|
virtual ScriptLanguage *get_language() const;
|
||||||
|
|
||||||
/* TODO */ virtual void get_script_method_list(List<MethodInfo> *p_list) const {}
|
virtual void get_script_method_list(List<MethodInfo> *p_list) const;
|
||||||
bool has_method(const StringName &p_method) const;
|
bool has_method(const StringName &p_method) const;
|
||||||
/* TODO */ MethodInfo get_method_info(const StringName &p_method) const { return MethodInfo(); }
|
MethodInfo get_method_info(const StringName &p_method) const;
|
||||||
|
|
||||||
virtual int get_member_line(const StringName &p_member) const;
|
virtual int get_member_line(const StringName &p_member) const;
|
||||||
|
|
||||||
|
|
|
@ -139,6 +139,20 @@ void GDMonoClass::fetch_attributes() {
|
||||||
attrs_fetched = true;
|
attrs_fetched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GDMonoClass::fetch_method_list() {
|
||||||
|
|
||||||
|
if (method_list_fetched)
|
||||||
|
return;
|
||||||
|
|
||||||
|
void *iter = NULL;
|
||||||
|
MonoMethod *raw_method = NULL;
|
||||||
|
while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
|
||||||
|
method_list.push_back(memnew(GDMonoMethod(mono_method_get_name(raw_method), raw_method)));
|
||||||
|
}
|
||||||
|
|
||||||
|
method_list_fetched = true;
|
||||||
|
}
|
||||||
|
|
||||||
void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) {
|
void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) {
|
||||||
|
|
||||||
CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this));
|
CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this));
|
||||||
|
@ -151,6 +165,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base
|
||||||
while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
|
while ((raw_method = mono_class_get_methods(get_mono_ptr(), &iter)) != NULL) {
|
||||||
StringName name = mono_method_get_name(raw_method);
|
StringName name = mono_method_get_name(raw_method);
|
||||||
|
|
||||||
|
// get_method implicitly fetches methods and adds them to this->methods
|
||||||
GDMonoMethod *method = get_method(raw_method, name);
|
GDMonoMethod *method = get_method(raw_method, name);
|
||||||
ERR_CONTINUE(!method);
|
ERR_CONTINUE(!method);
|
||||||
|
|
||||||
|
@ -449,6 +464,13 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() {
|
||||||
return delegates_list;
|
return delegates_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() {
|
||||||
|
if (!method_list_fetched)
|
||||||
|
fetch_method_list();
|
||||||
|
|
||||||
|
return method_list;
|
||||||
|
}
|
||||||
|
|
||||||
GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) {
|
GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) {
|
||||||
|
|
||||||
namespace_name = p_namespace;
|
namespace_name = p_namespace;
|
||||||
|
@ -460,6 +482,7 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name
|
||||||
attributes = NULL;
|
attributes = NULL;
|
||||||
|
|
||||||
methods_fetched = false;
|
methods_fetched = false;
|
||||||
|
method_list_fetched = false;
|
||||||
fields_fetched = false;
|
fields_fetched = false;
|
||||||
properties_fetched = false;
|
properties_fetched = false;
|
||||||
delegates_fetched = false;
|
delegates_fetched = false;
|
||||||
|
@ -512,4 +535,8 @@ GDMonoClass::~GDMonoClass() {
|
||||||
|
|
||||||
methods.clear();
|
methods.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < method_list.size(); ++i) {
|
||||||
|
memdelete(method_list[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,9 +79,14 @@ class GDMonoClass {
|
||||||
bool attrs_fetched;
|
bool attrs_fetched;
|
||||||
MonoCustomAttrInfo *attributes;
|
MonoCustomAttrInfo *attributes;
|
||||||
|
|
||||||
|
// This contains both the original method names and remapped method names from the native Godot identifiers to the C# functions.
|
||||||
|
// Most method-related functions refer to this and it's possible this is unintuitive for outside users; this may be a prime location for refactoring or renaming.
|
||||||
bool methods_fetched;
|
bool methods_fetched;
|
||||||
HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods;
|
HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods;
|
||||||
|
|
||||||
|
bool method_list_fetched;
|
||||||
|
Vector<GDMonoMethod *> method_list;
|
||||||
|
|
||||||
bool fields_fetched;
|
bool fields_fetched;
|
||||||
Map<StringName, GDMonoField *> fields;
|
Map<StringName, GDMonoField *> fields;
|
||||||
Vector<GDMonoField *> fields_list;
|
Vector<GDMonoField *> fields_list;
|
||||||
|
@ -97,6 +102,8 @@ class GDMonoClass {
|
||||||
friend class GDMonoAssembly;
|
friend class GDMonoAssembly;
|
||||||
GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
|
GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
|
||||||
|
|
||||||
|
void fetch_method_list();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static String get_full_name(MonoClass *p_mono_class);
|
static String get_full_name(MonoClass *p_mono_class);
|
||||||
static MonoType *get_mono_type(MonoClass *p_mono_class);
|
static MonoType *get_mono_type(MonoClass *p_mono_class);
|
||||||
|
@ -143,6 +150,8 @@ public:
|
||||||
|
|
||||||
const Vector<GDMonoClass *> &get_all_delegates();
|
const Vector<GDMonoClass *> &get_all_delegates();
|
||||||
|
|
||||||
|
const Vector<GDMonoMethod *> &get_all_methods();
|
||||||
|
|
||||||
~GDMonoClass();
|
~GDMonoClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
|
||||||
|
|
||||||
param_types.push_back(param_type);
|
param_types.push_back(param_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear the cache
|
||||||
|
method_info_fetched = false;
|
||||||
|
method_info = MethodInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GDMonoMethod::is_static() {
|
bool GDMonoMethod::is_static() {
|
||||||
|
@ -246,11 +250,34 @@ void GDMonoMethod::get_parameter_types(Vector<ManagedType> &types) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MethodInfo &GDMonoMethod::get_method_info() {
|
||||||
|
|
||||||
|
if (!method_info_fetched) {
|
||||||
|
method_info.name = name;
|
||||||
|
method_info.return_val = PropertyInfo(GDMonoMarshal::managed_to_variant_type(return_type), "");
|
||||||
|
|
||||||
|
Vector<StringName> names;
|
||||||
|
get_parameter_names(names);
|
||||||
|
|
||||||
|
for (int i = 0; i < params_count; ++i) {
|
||||||
|
method_info.arguments.push_back(PropertyInfo(GDMonoMarshal::managed_to_variant_type(param_types[i]), names[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: default arguments
|
||||||
|
|
||||||
|
method_info_fetched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method_info;
|
||||||
|
}
|
||||||
|
|
||||||
GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) {
|
GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) {
|
||||||
name = p_name;
|
name = p_name;
|
||||||
|
|
||||||
mono_method = p_method;
|
mono_method = p_method;
|
||||||
|
|
||||||
|
method_info_fetched = false;
|
||||||
|
|
||||||
attrs_fetched = false;
|
attrs_fetched = false;
|
||||||
attributes = NULL;
|
attributes = NULL;
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,9 @@ class GDMonoMethod : public GDMonoClassMember {
|
||||||
ManagedType return_type;
|
ManagedType return_type;
|
||||||
Vector<ManagedType> param_types;
|
Vector<ManagedType> param_types;
|
||||||
|
|
||||||
|
bool method_info_fetched;
|
||||||
|
MethodInfo method_info;
|
||||||
|
|
||||||
bool attrs_fetched;
|
bool attrs_fetched;
|
||||||
MonoCustomAttrInfo *attributes;
|
MonoCustomAttrInfo *attributes;
|
||||||
|
|
||||||
|
@ -83,6 +86,8 @@ public:
|
||||||
void get_parameter_names(Vector<StringName> &names) const;
|
void get_parameter_names(Vector<StringName> &names) const;
|
||||||
void get_parameter_types(Vector<ManagedType> &types) const;
|
void get_parameter_types(Vector<ManagedType> &types) const;
|
||||||
|
|
||||||
|
const MethodInfo &get_method_info();
|
||||||
|
|
||||||
GDMonoMethod(StringName p_name, MonoMethod *p_method);
|
GDMonoMethod(StringName p_name, MonoMethod *p_method);
|
||||||
~GDMonoMethod();
|
~GDMonoMethod();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue