-
-
Notifications
You must be signed in to change notification settings - Fork 21.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to print and log script backtraces #91006
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -120,11 +120,52 @@ class ResourceSaver : public Object { | |
ResourceSaver() { singleton = this; } | ||
}; | ||
|
||
class Logger : public RefCounted { | ||
GDCLASS(Logger, RefCounted); | ||
|
||
public: | ||
enum ErrorType { | ||
ERROR_TYPE_ERROR, | ||
ERROR_TYPE_WARNING, | ||
ERROR_TYPE_SCRIPT, | ||
ERROR_TYPE_SHADER | ||
}; | ||
|
||
protected: | ||
GDVIRTUAL2(_log_message, String, bool); | ||
GDVIRTUAL8(_log_error, String, String, int, String, String, bool, int, String); | ||
static void _bind_methods(); | ||
|
||
public: | ||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERROR_TYPE_ERROR, const char *p_script_backtrace = nullptr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how big of a deal this is, but if someone uses auto-complete (or just copies the signature verbatim) to implement this virtual method in GDScript, they will trigger the "Shadowed Global Identifier" warning due to the Maybe renaming the |
||
virtual void log_message(const String &p_text, bool p_error); | ||
}; | ||
|
||
class OS : public Object { | ||
GDCLASS(OS, Object); | ||
|
||
mutable HashMap<String, bool> feature_cache; | ||
|
||
class LoggerBind : public ::Logger { | ||
public: | ||
LocalVector<Ref<core_bind::Logger>> loggers; | ||
virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR, const char *p_script_backtrace = nullptr) override { | ||
if (!should_log(true)) { | ||
return; | ||
} | ||
|
||
for (uint32_t i = 0; i < loggers.size(); i++) { | ||
loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_editor_notify, core_bind::Logger::ErrorType(p_type), p_script_backtrace); | ||
} | ||
} | ||
|
||
virtual void logv(const char *p_format, va_list p_list, bool p_err) override _PRINTF_FORMAT_ATTRIBUTE_2_0; | ||
|
||
void clear() { loggers.clear(); } | ||
}; | ||
|
||
LoggerBind *logger_bind = nullptr; | ||
|
||
protected: | ||
static void _bind_methods(); | ||
static OS *singleton; | ||
|
@@ -275,9 +316,13 @@ class OS : public Object { | |
Vector<String> get_granted_permissions() const; | ||
void revoke_granted_permissions(); | ||
|
||
void add_logger(Ref<Logger> p_logger); | ||
void remove_logger(Ref<Logger> p_logger); | ||
|
||
static OS *get_singleton() { return singleton; } | ||
|
||
OS() { singleton = this; } | ||
OS(); | ||
~OS(); | ||
}; | ||
|
||
class Geometry2D : public Object { | ||
|
@@ -654,6 +699,7 @@ class EngineDebugger : public Object { | |
|
||
} // namespace core_bind | ||
|
||
VARIANT_ENUM_CAST(core_bind::Logger::ErrorType); | ||
VARIANT_ENUM_CAST(core_bind::ResourceLoader::ThreadLoadStatus); | ||
VARIANT_ENUM_CAST(core_bind::ResourceLoader::CacheMode); | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -518,6 +518,21 @@ void ScriptServer::save_global_classes() { | |||||
ProjectSettings::get_singleton()->store_global_class_list(gcarr); | ||||||
} | ||||||
|
||||||
String ScriptServer::get_current_script_backtrace() { | ||||||
String trace; | ||||||
for (int si = 0; si < get_language_count(); si++) { | ||||||
ScriptLanguage *sl = get_language(si); | ||||||
Vector<ScriptLanguage::StackInfo> stack = sl->debug_get_current_stack_info(); | ||||||
if (stack.size()) { | ||||||
trace += "stack_language: " + sl->get_name(); | ||||||
for (int i = 0; i < stack.size(); i++) { | ||||||
trace += "\n" + itos(i) + ": " + stack[i].func + " (" + stack[i].file + " : " + itos(stack[i].line) + ")"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seeing as how the existing error/warning printing formats file-with-line as
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. makes sense |
||||||
} | ||||||
} | ||||||
} | ||||||
return trace; | ||||||
} | ||||||
|
||||||
//////////////////// | ||||||
|
||||||
ScriptCodeCompletionCache *ScriptCodeCompletionCache::singleton = nullptr; | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seeing as how
_log_message
will end up getting called on everyprint
, you can fairly easily get yourself into a stack overflow by trying toprint
anything from_log_message
.Might be good to mention in the documentation at least.
EDIT: I would assume the same applies when trying to
push_error
from_log_error
.