Merge pull request #23438 from zorbathut/zorbathut/csharpinstance

Implement CSharpScript::get_script_method_list and related functionality.
This commit is contained in:
Ignacio Etcheverry 2018-12-08 22:08:18 +01:00 committed by GitHub
commit c9550b800a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 2 deletions

View File

@ -2474,6 +2474,18 @@ 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;
// TODO: Filter out things unsuitable for explicit calls, like constructors.
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 +2494,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;

View File

@ -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;

View File

@ -151,6 +151,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 +450,21 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() {
return delegates_list; return delegates_list;
} }
const Vector<GDMonoMethod *> &GDMonoClass::get_all_methods() {
if (!method_list_fetched) {
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;
}
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 +476,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 +529,8 @@ GDMonoClass::~GDMonoClass() {
methods.clear(); methods.clear();
} }
for (int i = 0; i < method_list.size(); ++i) {
memdelete(method_list[i]);
}
} }

View File

@ -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;
@ -143,6 +148,8 @@ public:
const Vector<GDMonoClass *> &get_all_delegates(); const Vector<GDMonoClass *> &get_all_delegates();
const Vector<GDMonoMethod *> &get_all_methods();
~GDMonoClass(); ~GDMonoClass();
}; };

View File

@ -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;

View File

@ -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();
}; };