You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-06 12:20:30 +00:00
Parse C# script namespace and class
- Added a very simple parser that can extract the namespace and class name of a C# script.
This commit is contained in:
@@ -30,11 +30,15 @@
|
||||
|
||||
#include "csharp_project.h"
|
||||
|
||||
#include "core/io/json.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/project_settings.h"
|
||||
|
||||
#include "../csharp_script.h"
|
||||
#include "../mono_gd/gd_mono_class.h"
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../utils/string_utils.h"
|
||||
#include "script_class_parser.h"
|
||||
|
||||
namespace CSharpProject {
|
||||
|
||||
@@ -118,4 +122,109 @@ void add_item(const String &p_project_path, const String &p_item_type, const Str
|
||||
ERR_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
Error generate_scripts_metadata(const String &p_project_path, const String &p_output_path) {
|
||||
|
||||
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
|
||||
|
||||
GDMonoClass *project_utils = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
|
||||
|
||||
void *args[2] = {
|
||||
GDMonoMarshal::mono_string_from_godot(p_project_path),
|
||||
GDMonoMarshal::mono_string_from_godot("Compile")
|
||||
};
|
||||
|
||||
MonoException *exc = NULL;
|
||||
MonoArray *ret = (MonoArray *)project_utils->get_method("GetIncludeFiles", 2)->invoke_raw(NULL, args, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
ERR_FAIL_V(FAILED);
|
||||
}
|
||||
|
||||
PoolStringArray project_files = GDMonoMarshal::mono_array_to_PoolStringArray(ret);
|
||||
PoolStringArray::Read r = project_files.read();
|
||||
|
||||
Dictionary old_dict = CSharpLanguage::get_singleton()->get_scripts_metadata();
|
||||
Dictionary new_dict;
|
||||
|
||||
for (int i = 0; i < project_files.size(); i++) {
|
||||
const String &project_file = ("res://" + r[i]).simplify_path();
|
||||
|
||||
uint64_t modified_time = FileAccess::get_modified_time(project_file);
|
||||
|
||||
const Variant *old_file_var = old_dict.getptr(project_file);
|
||||
if (old_file_var) {
|
||||
Dictionary old_file_dict = old_file_var->operator Dictionary();
|
||||
|
||||
if (old_file_dict["modified_time"].operator uint64_t() == modified_time) {
|
||||
// No changes so no need to parse again
|
||||
new_dict[project_file] = old_file_dict;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ScriptClassParser scp;
|
||||
Error err = scp.parse_file(project_file);
|
||||
if (err != OK) {
|
||||
ERR_EXPLAIN("Failed to determine namespace and class for script: " + project_file);
|
||||
ERR_FAIL_V(err);
|
||||
}
|
||||
|
||||
Vector<ScriptClassParser::ClassDecl> classes = scp.get_classes();
|
||||
|
||||
bool found = false;
|
||||
Dictionary class_dict;
|
||||
|
||||
String search_name = project_file.get_file().get_basename();
|
||||
|
||||
for (int j = 0; j < classes.size(); j++) {
|
||||
const ScriptClassParser::ClassDecl &class_decl = classes[j];
|
||||
|
||||
if (class_decl.base.size() == 0)
|
||||
continue; // Does not inherit nor implement anything, so it can't be a script class
|
||||
|
||||
String class_cmp;
|
||||
|
||||
if (class_decl.nested) {
|
||||
class_cmp = class_decl.name.get_slice(".", class_decl.name.get_slice_count(".") - 1);
|
||||
} else {
|
||||
class_cmp = class_decl.name;
|
||||
}
|
||||
|
||||
if (class_cmp != search_name)
|
||||
continue;
|
||||
|
||||
class_dict["namespace"] = class_decl.namespace_;
|
||||
class_dict["class_name"] = class_decl.name;
|
||||
class_dict["nested"] = class_decl.nested;
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
Dictionary file_dict;
|
||||
file_dict["modified_time"] = modified_time;
|
||||
file_dict["class"] = class_dict;
|
||||
new_dict[project_file] = file_dict;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_dict.size()) {
|
||||
String json = JSON::print(new_dict, "", false);
|
||||
|
||||
Error ferr;
|
||||
FileAccess *f = FileAccess::open(p_output_path, FileAccess::WRITE, &ferr);
|
||||
ERR_EXPLAIN("Cannot open file for writing: " + p_output_path);
|
||||
ERR_FAIL_COND_V(ferr != OK, ferr);
|
||||
f->store_string(json);
|
||||
f->flush();
|
||||
f->close();
|
||||
memdelete(f);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
} // namespace CSharpProject
|
||||
|
||||
Reference in New Issue
Block a user