summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
authorBen Rog-Wilhelm <zorba-githubdesktop20180420@pavlovian.net>2018-11-01 08:35:16 -0700
committerBen Rog-Wilhelm <zorba-git20110501@pavlovian.net>2018-12-07 23:54:40 -0800
commitf13f2d512f0439a29804182cee756dce62add857 (patch)
tree3eeb1fb32881c29ca3c6930c6073ba8ac9f57b8c /modules/mono
parent41d1dba35fc851258d5aabad819d09f6a43e324c (diff)
Implement CSharpScript::get_script_method_list and related functionality.
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/csharp_script.cpp30
-rw-r--r--modules/mono/csharp_script.h4
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp27
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h9
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp27
-rw-r--r--modules/mono/mono_gd/gd_mono_method.h5
6 files changed, 100 insertions, 2 deletions
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 3c818898e6..ba31f12d37 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -2474,6 +2474,17 @@ void CSharpScript::set_source_code(const String &p_code) {
#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 {
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);
}
+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) {
bool has_instances;
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
index 501e0d9d6d..08466bae58 100644
--- a/modules/mono/csharp_script.h
+++ b/modules/mono/csharp_script.h
@@ -174,9 +174,9 @@ public:
virtual Ref<Script> get_base_script() 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;
- /* 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;
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
index 4e515cde28..400735bb20 100644
--- a/modules/mono/mono_gd/gd_mono_class.cpp
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -139,6 +139,20 @@ void GDMonoClass::fetch_attributes() {
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) {
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) {
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);
ERR_CONTINUE(!method);
@@ -449,6 +464,13 @@ const Vector<GDMonoClass *> &GDMonoClass::get_all_delegates() {
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) {
namespace_name = p_namespace;
@@ -460,6 +482,7 @@ GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name
attributes = NULL;
methods_fetched = false;
+ method_list_fetched = false;
fields_fetched = false;
properties_fetched = false;
delegates_fetched = false;
@@ -512,4 +535,8 @@ GDMonoClass::~GDMonoClass() {
methods.clear();
}
+
+ for (int i = 0; i < method_list.size(); ++i) {
+ memdelete(method_list[i]);
+ }
}
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
index 477305d503..4199eb22c6 100644
--- a/modules/mono/mono_gd/gd_mono_class.h
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -79,9 +79,14 @@ class GDMonoClass {
bool attrs_fetched;
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;
HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods;
+ bool method_list_fetched;
+ Vector<GDMonoMethod *> method_list;
+
bool fields_fetched;
Map<StringName, GDMonoField *> fields;
Vector<GDMonoField *> fields_list;
@@ -97,6 +102,8 @@ class GDMonoClass {
friend class GDMonoAssembly;
GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
+ void fetch_method_list();
+
public:
static String get_full_name(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<GDMonoMethod *> &get_all_methods();
+
~GDMonoClass();
};
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
index 630bda8b4e..6ef6e97f5a 100644
--- a/modules/mono/mono_gd/gd_mono_method.cpp
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -68,6 +68,10 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
param_types.push_back(param_type);
}
+
+ // clear the cache
+ method_info_fetched = false;
+ method_info = MethodInfo();
}
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) {
name = p_name;
mono_method = p_method;
+ method_info_fetched = false;
+
attrs_fetched = false;
attributes = NULL;
diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h
index 444ec2a67d..6c3ae5fce0 100644
--- a/modules/mono/mono_gd/gd_mono_method.h
+++ b/modules/mono/mono_gd/gd_mono_method.h
@@ -43,6 +43,9 @@ class GDMonoMethod : public GDMonoClassMember {
ManagedType return_type;
Vector<ManagedType> param_types;
+ bool method_info_fetched;
+ MethodInfo method_info;
+
bool attrs_fetched;
MonoCustomAttrInfo *attributes;
@@ -83,6 +86,8 @@ public:
void get_parameter_names(Vector<StringName> &names) const;
void get_parameter_types(Vector<ManagedType> &types) const;
+ const MethodInfo &get_method_info();
+
GDMonoMethod(StringName p_name, MonoMethod *p_method);
~GDMonoMethod();
};