Skip to content
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

Improve error messages for invalid property access/calls in GDScript #46241

Closed
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
2 changes: 1 addition & 1 deletion modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
} else {
switch (base.builtin_type) {
case Variant::NIL: {
push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier);
push_error(vformat(R"(Value of type Nil does not have the attribute "%s".)", name), p_identifier);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have information about what identifier is of type Nil? Or would that be explicit enough from the stacktrace?

Copy link
Contributor

@ThakeeNathees ThakeeNathees Feb 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder why the keyword literal is null and its name is nil. They have different meanings in some other languages (like Objective C, Scala). In general, NULL is 0 or '\0' in ASCII and Nil is emptiness. (I'd like it as null)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this in a GDScript meeting and suggest indeed referring to null directly. Maybe this could be:

Suggested change
push_error(vformat(R"(Value of type Nil does not have the attribute "%s".)", name), p_identifier);
push_error(vformat(R"(Could not get attribute "%s" on a null value.)", name), p_identifier);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or the same phrasing as used in your VM changes to be consistent.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or the same phrasing as used in your VM changes to be consistent.

Which changes are you referring to? I may have forgotten something 🙂

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the sentence you used for the null case in gdscript_vm.cpp:

err_text = "Tried to access attribute " + v + " on a value that is null.";

return;
}
case Variant::DICTIONARY: {
Expand Down
24 changes: 20 additions & 4 deletions modules/gdscript/gdscript_vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(index) + "'";
}
err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
if (!src->is_null()) {
err_text = "Tried to access attribute " + v + " on a value that is null.";
} else {
err_text = "Value of type '" + _get_var_type(src) + "' does not have the attribute " + v + ".";
}
Comment on lines +811 to +815
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the condition backwards here?

OPCODE_BREAK;
}
*dst = ret;
Expand Down Expand Up @@ -844,7 +848,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(key) + "'";
}
err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
if (!src->is_null()) {
err_text = "Tried to access attribute " + v + " on a value that is null.";
} else {
err_text = "Value of type '" + _get_var_type(src) + "' does not have the attribute " + v + ".";
}
OPCODE_BREAK;
}
*dst = ret;
Expand Down Expand Up @@ -947,9 +955,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
if (!valid) {
if (src->has_method(*index)) {
err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?";
if (!src->is_null()) {
err_text = "Tried to access attribute '" + index->operator String() + "' on a value that is null. Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?";
} else {
err_text = "Value of type '" + _get_var_type(src) + "' does not have the attribute '" + index->operator String() + "'. Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?";
}
} else {
err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
if (!src->is_null()) {
err_text = "Tried to access attribute '" + index->operator String() + "' on a value that is null.";
} else {
err_text = "Value of type '" + _get_var_type(src) + "' does not have the attribute '" + index->operator String() + "'.";
}
}
OPCODE_BREAK;
}
Expand Down