Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/static_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ jobs:

- name: Spell checks via codespell
if: github.event_name == 'pull_request' && env.CHANGED_FILES != ''
uses: codespell-project/actions-codespell@v1
uses: codespell-project/actions-codespell@v2
with:
skip: "./bin,./thirdparty,*.desktop,*.gen.*,*.po,*.pot,*.rc,./AUTHORS.md,./COPYRIGHT.txt,./DONORS.md,./core/input/gamecontrollerdb.txt,./core/string/locales.h,./editor/project_converter_3_to_4.cpp,./misc/scripts/codespell.sh,./platform/android/java/lib/src/com,./platform/web/node_modules,./platform/web/package-lock.json"
ignore_words_list: "curvelinear,doubleclick,expct,findn,gird,hel,inout,lod,nd,numer,ot,te,vai"
ignore_words_list: "breaked,checkin,curvelinear,doubleclick,expct,findn,gird,hel,inout,labelin,lod,mis,nd,numer,ot,pointin,requestor,te,textin,thirdparty,vai"
path: ${{ env.CHANGED_FILES }}
1 change: 1 addition & 0 deletions SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,5 @@ env_module.Append(CPPPATH=["#modules/javascript"])
env_module.add_source_files(env.modules_sources, sources)

if env.editor_build:
env_module.add_source_files(env.modules_sources, "editor/workarounds/*.cpp")
env_module.add_source_files(env.modules_sources, "editor/*.cpp")
214 changes: 114 additions & 100 deletions editor/editor_tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,82 @@
return ret;
}

static String format_enum_name(const String &enum_name) {
if (enum_name.begins_with("Variant.")) {
return enum_name.replace(".", "");
}
return enum_name;
}

void JavaScriptPlugin::_export_enumeration_binding_file(const String &p_path) {
_export_typescript_declare_file("");
String file_content = "// Tool generated file DO NOT modify manually\n"
"// Add this script as first autoload to your project to bind enumerations for release build of godot engine\n"
"\n"
"if (!godot.DEBUG_ENABLED) {\n"
"\tfunction bind(cls, enumerations) {\n"
"\t\tif (cls) Object.defineProperties(cls, enumerations);\n"
"\t};\n"
"\n"
"${enumerations}"
"}\n"
"export default class extends godot.Node {};\n";

String enumerations = "";
for (const auto &cls : class_enumerations) {
const ClassEnumerations &enumeration = cls.value;
const String &name = cls.key;
String class_name = name;
if (class_name != "godot") {
class_name = "godot." + class_name;
}
String class_enums = "";
uint32_t idx = 0;
for (const auto &E : enumeration) {
String enum_items_text = "{";
const Vector<const DocData::ConstantDoc *> &consts = E.value;
for (int i = 0; i < consts.size(); ++i) {
const DocData::ConstantDoc *c = consts[i];
enum_items_text += c->name + ": " + c->value;
if (i < consts.size() - 1) {
enum_items_text += ", ";
}
}
enum_items_text += " }";
Dictionary new_dict;
new_dict["name"] = format_enum_name(E.key);
new_dict["values"] = enum_items_text;
class_enums += apply_pattern("\n\t\t${name}: { value: ${values} }", new_dict);
if (idx < enumeration.size() - 1) {
class_enums += ", ";
} else {
class_enums += "\n\t";
}
idx++;
}
static String class_template = "\tbind(${class}, {${enumerations}});\n";
Dictionary class_dict;
class_dict["class"] = class_name;
class_dict["enumerations"] = class_enums;
enumerations += apply_pattern(class_template, class_dict);
}
Dictionary enum_dict;
enum_dict["enumerations"] = enumerations;
file_content = apply_pattern(file_content, enum_dict);

dump_to_file(p_path, file_content);
}

void JavaScriptPlugin::_generate_typescript_project() {
_export_typescript_declare_file("res://godot.d.ts");
dump_to_file("res://tsconfig.json", TSCONFIG_CONTENT);
dump_to_file("res://decorators.ts", TS_DECORATORS_CONTENT);
dump_to_file("res://package.json", PACKAGE_JSON_CONTENT);
}

// The following functions are used to generate a godot.d.ts file out of the docs folder from godot
#pragma region TS declare file

Check warning on line 227 in editor/editor_tools.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

ignoring #pragma region TS [-Wunknown-pragmas]

static String format_doc_text(const String &p_bbcode, const String &p_indent = "\t") {
String markdown = p_bbcode.strip_edges();

Expand Down Expand Up @@ -222,16 +298,15 @@
return p_ident;
}

static String format_enum_name(const String &enum_name) {
if (enum_name.begins_with("Variant.")) {
return enum_name.replace(".", "");
}
return enum_name;
}

static String get_type_name(const String &p_type) {
if (p_type.is_empty())
if (p_type.is_empty() || p_type == "void")
return "void";

if (p_type.ends_with("[]")) {
String base_type = p_type.substr(0, p_type.length() - 2);
return "Array<" + get_type_name(base_type) + ">";
}

if (p_type == "int" || p_type == "float")
return "number";
if (p_type == "bool")
Expand All @@ -242,8 +317,10 @@
return "any[]";
if (p_type == "Dictionary")
return "object";
if (p_type == "Variant")
if (p_type == "Variant" || p_type.contains("*"))
return "any";
if (p_type == "StringName")
return "StringName | string";
return p_type;
}

Expand Down Expand Up @@ -276,6 +353,11 @@
}
} else {
default_value += arg.default_value;
// we don't want to have pointers or addresses in TS
default_value = default_value
.replace("&", "")
.replace("*", "")
.replace("**", "");
}
}

Expand Down Expand Up @@ -316,17 +398,23 @@
return apply_pattern(method_template, dict);
}

String _export_class(const DocData::ClassDoc &class_doc) {
/* This function generates all classes for godot.d.ts based on DocData::ClassDoc */
String _export_class(const DocData::ClassDoc &class_doc,
Dictionary missing_constructors,
Dictionary missing_enums,
Array ignore_methods) {
String class_template = "\n"
"\t/** ${brief_description}\n"
"\t ${description} */\n"
"${TS_IGNORE}"
"\tclass ${name}${extends}${inherits} {\n"
"${missingConstructors}"
"${properties}"
"${methods}"
"${extrals}"
"\t}\n"
"\tnamespace ${name} {\n"
"${missingEnums}"
"${signals}"
"${enumerations}"
"${constants}"
Expand All @@ -345,6 +433,9 @@
dict["description"] = description;
}

dict["missingConstructors"] = missing_constructors.get(class_doc.name, "");
dict["missingEnums"] = missing_enums.get(class_doc.name, "");

HashSet<String> ignore_members;
if (removed_members.has(class_doc.name)) {
ignore_members = removed_members[class_doc.name];
Expand Down Expand Up @@ -439,15 +530,15 @@
new_dict["static"] = Engine::get_singleton()->has_singleton(class_doc.name) ? "static " : "";
properties += apply_pattern(prop_str, new_dict);

if (!prop_doc.getter.is_empty()) {
if (!prop_doc.getter.is_empty() && !ignore_methods.has(prop_doc.getter)) {
DocData::MethodDoc md;
md.name = prop_doc.getter;
md.return_type = get_type_name(prop_doc.type);
md.description = String("Getter of `") + prop_doc.name + "` property";
method_list.push_back(md);
}

if (!prop_doc.setter.is_empty()) {
if (!prop_doc.setter.is_empty() && !ignore_methods.has(prop_doc.setter)) {
DocData::MethodDoc md;
md.name = prop_doc.setter;
DocData::ArgumentDoc arg;
Expand Down Expand Up @@ -566,27 +657,6 @@
ignored_classes.insert("Variant");
ignored_classes.insert("Array");
ignored_classes.insert("Dictionary");
#if 1
ignored_classes.insert("Vector2");
ignored_classes.insert("Vector3");
ignored_classes.insert("Color");
ignored_classes.insert("Rect2");
ignored_classes.insert("RID");
ignored_classes.insert("NodePath");
ignored_classes.insert("Transform2D");
ignored_classes.insert("Transform3D");
ignored_classes.insert("Basis");
ignored_classes.insert("Quaternion");
ignored_classes.insert("Plane");
ignored_classes.insert("AABB");
ignored_classes.insert("PackedByteArray");
ignored_classes.insert("PackedInt32Array");
ignored_classes.insert("PackedFloat32Array");
ignored_classes.insert("PackedStringArray");
ignored_classes.insert("PackedVector2Array");
ignored_classes.insert("PackedVector3Array");
ignored_classes.insert("PackedColorArray");
#endif
ignored_classes.insert("Semaphore");
ignored_classes.insert("Thread");
ignored_classes.insert("Mutex");
Expand All @@ -601,7 +671,11 @@
if (ignored_classes.has(class_doc.name)) {
continue;
}
class_doc.name = get_type_name(class_doc.name);

if (class_doc.name != "StringName" && class_doc.name != "NodePath") {
class_doc.name = get_type_name(class_doc.name);
}

if (class_doc.name.begins_with("@")) {
HashMap<String, Vector<const DocData::ConstantDoc *>> enumerations;
if (class_doc.name == "@GlobalScope" || class_doc.name == "@GDScript") {
Expand Down Expand Up @@ -666,7 +740,11 @@
}
continue;
}
classes += _export_class(class_doc);
classes += _export_class(
class_doc,
DECLARATION_CONSTRUCTORS,
DECLARATION_ENUMS,
IGNORE_METHODS);
}
dict["classes"] = classes;
dict["constants"] = constants;
Expand All @@ -681,70 +759,6 @@
}
}

void JavaScriptPlugin::_export_enumeration_binding_file(const String &p_path) {
_export_typescript_declare_file("");
String file_content = "// Tool generated file DO NOT modify manually\n"
"// Add this script as first autoload to your project to bind enumerations for release build of godot engine\n"
"\n"
"if (!godot.DEBUG_ENABLED) {\n"
"\tfunction bind(cls, enumerations) {\n"
"\t\tif (cls) Object.defineProperties(cls, enumerations);\n"
"\t};\n"
"\n"
"${enumerations}"
"}\n"
"export default class extends godot.Node {};\n";

String enumerations = "";
for (const auto &cls : class_enumerations) {
const ClassEnumerations &enumeration = cls.value;
const String &name = cls.key;
String class_name = name;
if (class_name != "godot") {
class_name = "godot." + class_name;
}
String class_enums = "";
uint32_t idx = 0;
for (const auto &E : enumeration) {
String enum_items_text = "{";
const Vector<const DocData::ConstantDoc *> &consts = E.value;
for (int i = 0; i < consts.size(); ++i) {
const DocData::ConstantDoc *c = consts[i];
enum_items_text += c->name + ": " + c->value;
if (i < consts.size() - 1) {
enum_items_text += ", ";
}
}
enum_items_text += " }";
Dictionary new_dict;
new_dict["name"] = format_enum_name(E.key);
new_dict["values"] = enum_items_text;
class_enums += apply_pattern("\n\t\t${name}: { value: ${values} }", new_dict);
if (idx < enumeration.size() - 1) {
class_enums += ", ";
} else {
class_enums += "\n\t";
}
idx++;
}
static String class_template = "\tbind(${class}, {${enumerations}});\n";
Dictionary class_dict;
class_dict["class"] = class_name;
class_dict["enumerations"] = class_enums;
enumerations += apply_pattern(class_template, class_dict);
}
Dictionary enum_dict;
enum_dict["enumerations"] = enumerations;
file_content = apply_pattern(file_content, enum_dict);

dump_to_file(p_path, file_content);
}

void JavaScriptPlugin::_generate_typescript_project() {
_export_typescript_declare_file("res://godot.d.ts");
dump_to_file("res://tsconfig.json", TSCONFIG_CONTENT);
dump_to_file("res://decorators.ts", TS_DECORATORS_CONTENT);
dump_to_file("res://package.json", PACKAGE_JSON_CONTENT);
}
#pragma endregion TS declare file

Check warning on line 762 in editor/editor_tools.cpp

View workflow job for this annotation

GitHub Actions / 🐧 Linux / Editor w/ Mono (target=editor)

ignoring #pragma endregion TS [-Wunknown-pragmas]

#endif // TOOLS_ENABLED
6 changes: 6 additions & 0 deletions editor/editor_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,17 @@ class JavaScriptPlugin : public EditorPlugin {
const Dictionary *modified_api;

protected:
/* Strings will be generated by ./SCsub from misc directory */
static String BUILTIN_DECLARATION_TEXT;
static String TSCONFIG_CONTENT;
static String TS_DECORATORS_CONTENT;
static String PACKAGE_JSON_CONTENT;

/* Missing declarations, ignoring*/
static Dictionary DECLARATION_CONSTRUCTORS;
static Dictionary DECLARATION_ENUMS;
static Array IGNORE_METHODS;

static void _bind_methods();

void _notification(int p_what);
Expand Down
43 changes: 43 additions & 0 deletions editor/workarounds/ignore-methods.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**************************************************************************/
/* ignore-methods.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

/* All types are generated in editor_tools, but constructors are missing we need to add them manually. */

#include "../editor_tools.h"

Array create_ignore_methods() {
Array array = Array();
array.push_back("get_flag");
array.push_back("set_flag");
array.push_back("set_play_area_mode");
return array;
}

Array JavaScriptPlugin::IGNORE_METHODS = create_ignore_methods();
Loading
Loading