|
@@ -28,7 +28,6 @@
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
|
|
-#include "core/string/print_string.h"
|
|
|
|
#include "gdscript.h"
|
|
#include "gdscript.h"
|
|
|
|
|
|
#include "gdscript_analyzer.h"
|
|
#include "gdscript_analyzer.h"
|
|
@@ -1126,25 +1125,19 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
|
|
base_type = GDScriptParser::DataType();
|
|
base_type = GDScriptParser::DataType();
|
|
} break;
|
|
} break;
|
|
case GDScriptParser::DataType::SCRIPT: {
|
|
case GDScriptParser::DataType::SCRIPT: {
|
|
- print_line("identifier script");
|
|
|
|
Ref<Script> scr = base_type.script_type;
|
|
Ref<Script> scr = base_type.script_type;
|
|
if (scr.is_valid()) {
|
|
if (scr.is_valid()) {
|
|
if (p_types_only) {
|
|
if (p_types_only) {
|
|
// TODO: Need to implement Script::get_script_enum_list and retrieve the enum list from a script.
|
|
// TODO: Need to implement Script::get_script_enum_list and retrieve the enum list from a script.
|
|
} else if (!p_only_functions) {
|
|
} else if (!p_only_functions) {
|
|
if (!base_type.is_meta_type) {
|
|
if (!base_type.is_meta_type) {
|
|
- print_line("no meta type");
|
|
|
|
List<PropertyInfo> members;
|
|
List<PropertyInfo> members;
|
|
scr->get_script_property_list(&members);
|
|
scr->get_script_property_list(&members);
|
|
- print_line("scripts", members.size());
|
|
|
|
for (const PropertyInfo &E : members) {
|
|
for (const PropertyInfo &E : members) {
|
|
- print_line(E.name);
|
|
|
|
if (E.usage & (PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_INTERNAL)) {
|
|
if (E.usage & (PROPERTY_USAGE_CATEGORY | PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SUBGROUP | PROPERTY_USAGE_INTERNAL)) {
|
|
- print_line("filtered 1");
|
|
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
if (E.name.contains("/")) {
|
|
if (E.name.contains("/")) {
|
|
- print_line("filtered 2");
|
|
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
int location = p_recursion_depth + _get_property_location(scr, E.name);
|
|
int location = p_recursion_depth + _get_property_location(scr, E.name);
|
|
@@ -2051,7 +2044,6 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
|
|
}
|
|
}
|
|
|
|
|
|
static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::IdentifierNode *p_identifier, GDScriptCompletionIdentifier &r_type) {
|
|
static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::IdentifierNode *p_identifier, GDScriptCompletionIdentifier &r_type) {
|
|
- print_line("guess identifier type");
|
|
|
|
static int recursion_depth = 0;
|
|
static int recursion_depth = 0;
|
|
RecursionCheck recursion(&recursion_depth);
|
|
RecursionCheck recursion(&recursion_depth);
|
|
if (unlikely(recursion.check())) {
|
|
if (unlikely(recursion.check())) {
|
|
@@ -2110,9 +2102,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- print_line("not local");
|
|
|
|
if (p_context.current_class) {
|
|
if (p_context.current_class) {
|
|
- print_line("current class exists");
|
|
|
|
GDScriptCompletionIdentifier base_identifier;
|
|
GDScriptCompletionIdentifier base_identifier;
|
|
|
|
|
|
GDScriptCompletionIdentifier base;
|
|
GDScriptCompletionIdentifier base;
|
|
@@ -2183,7 +2173,6 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
|
|
if (_guess_expression_type(c, last_assigned_expression, assigned_type)) {
|
|
if (_guess_expression_type(c, last_assigned_expression, assigned_type)) {
|
|
if (id_type.is_set() && assigned_type.type.is_set() && !GDScriptAnalyzer::check_type_compatibility(id_type, assigned_type.type)) {
|
|
if (id_type.is_set() && assigned_type.type.is_set() && !GDScriptAnalyzer::check_type_compatibility(id_type, assigned_type.type)) {
|
|
// The assigned type is incompatible. The annotated type takes priority.
|
|
// The assigned type is incompatible. The annotated type takes priority.
|
|
- print_line("Just here for testing.");
|
|
|
|
r_type.assigned_expression = last_assigned_expression;
|
|
r_type.assigned_expression = last_assigned_expression;
|
|
r_type.type = id_type;
|
|
r_type.type = id_type;
|
|
} else {
|
|
} else {
|
|
@@ -2300,7 +2289,6 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
|
|
}
|
|
}
|
|
|
|
|
|
static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) {
|
|
static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_identifier, GDScriptCompletionIdentifier &r_type) {
|
|
- print_line("_guess_identifier_type_from_base");
|
|
|
|
static int recursion_depth = 0;
|
|
static int recursion_depth = 0;
|
|
RecursionCheck recursion(&recursion_depth);
|
|
RecursionCheck recursion(&recursion_depth);
|
|
if (unlikely(recursion.check())) {
|
|
if (unlikely(recursion.check())) {
|
|
@@ -2312,9 +2300,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
|
|
while (base_type.is_set()) {
|
|
while (base_type.is_set()) {
|
|
switch (base_type.kind) {
|
|
switch (base_type.kind) {
|
|
case GDScriptParser::DataType::CLASS:
|
|
case GDScriptParser::DataType::CLASS:
|
|
- print_line("CLASS");
|
|
|
|
if (base_type.class_type->has_member(p_identifier)) {
|
|
if (base_type.class_type->has_member(p_identifier)) {
|
|
- print_line("has member");
|
|
|
|
const GDScriptParser::ClassNode::Member &member = base_type.class_type->get_member(p_identifier);
|
|
const GDScriptParser::ClassNode::Member &member = base_type.class_type->get_member(p_identifier);
|
|
switch (member.type) {
|
|
switch (member.type) {
|
|
case GDScriptParser::ClassNode::Member::CONSTANT:
|
|
case GDScriptParser::ClassNode::Member::CONSTANT:
|
|
@@ -2324,40 +2310,29 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
case GDScriptParser::ClassNode::Member::VARIABLE:
|
|
case GDScriptParser::ClassNode::Member::VARIABLE:
|
|
- print_line("variable");
|
|
|
|
if (!is_static || member.variable->is_static) {
|
|
if (!is_static || member.variable->is_static) {
|
|
- print_line("1");
|
|
|
|
if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
|
|
if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
|
|
- print_line("2");
|
|
|
|
r_type.type = member.variable->get_datatype();
|
|
r_type.type = member.variable->get_datatype();
|
|
return true;
|
|
return true;
|
|
} else if (member.variable->initializer) {
|
|
} else if (member.variable->initializer) {
|
|
- print_line("3");
|
|
|
|
const GDScriptParser::ExpressionNode *init = member.variable->initializer;
|
|
const GDScriptParser::ExpressionNode *init = member.variable->initializer;
|
|
if (init->is_constant) {
|
|
if (init->is_constant) {
|
|
- print_line("4");
|
|
|
|
r_type.value = init->reduced_value;
|
|
r_type.value = init->reduced_value;
|
|
r_type = _type_from_variant(init->reduced_value, p_context);
|
|
r_type = _type_from_variant(init->reduced_value, p_context);
|
|
return true;
|
|
return true;
|
|
} else if (init->start_line == p_context.current_line) {
|
|
} else if (init->start_line == p_context.current_line) {
|
|
- print_line("5");
|
|
|
|
return false;
|
|
return false;
|
|
// Detects if variable is assigned to itself
|
|
// Detects if variable is assigned to itself
|
|
} else if (_is_expression_named_identifier(init, member.variable->identifier->name)) {
|
|
} else if (_is_expression_named_identifier(init, member.variable->identifier->name)) {
|
|
- print_line("6");
|
|
|
|
if (member.variable->initializer->get_datatype().is_set()) {
|
|
if (member.variable->initializer->get_datatype().is_set()) {
|
|
- print_line("7");
|
|
|
|
r_type.type = member.variable->initializer->get_datatype();
|
|
r_type.type = member.variable->initializer->get_datatype();
|
|
} else if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
|
|
} else if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) {
|
|
- print_line("8");
|
|
|
|
r_type.type = member.variable->get_datatype();
|
|
r_type.type = member.variable->get_datatype();
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
} else if (_guess_expression_type(p_context, init, r_type)) {
|
|
} else if (_guess_expression_type(p_context, init, r_type)) {
|
|
- print_line("9");
|
|
|
|
return true;
|
|
return true;
|
|
} else if (init->get_datatype().is_set() && !init->get_datatype().is_variant()) {
|
|
} else if (init->get_datatype().is_set() && !init->get_datatype().is_variant()) {
|
|
- print_line("10");
|
|
|
|
r_type.type = init->get_datatype();
|
|
r_type.type = init->get_datatype();
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -2859,7 +2834,6 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
}
|
|
}
|
|
|
|
|
|
static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
|
|
static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, const GDScriptParser::SubscriptNode *p_subscript, GDScriptParser::DataType &r_base_type, Variant *r_base = nullptr) {
|
|
- print_line("get subscript type");
|
|
|
|
if (p_context.base == nullptr) {
|
|
if (p_context.base == nullptr) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -2872,13 +2846,10 @@ static bool _get_subscript_type(GDScriptParser::CompletionContext &p_context, co
|
|
} break;
|
|
} break;
|
|
|
|
|
|
case GDScriptParser::Node::IDENTIFIER: {
|
|
case GDScriptParser::Node::IDENTIFIER: {
|
|
- print_line("identifier");
|
|
|
|
if (p_subscript->base->datatype.type_source == GDScriptParser::DataType::ANNOTATED_EXPLICIT) {
|
|
if (p_subscript->base->datatype.type_source == GDScriptParser::DataType::ANNOTATED_EXPLICIT) {
|
|
- print_line("annotated type takes precedence");
|
|
|
|
// Annotated type takes precedence.
|
|
// Annotated type takes precedence.
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
- print_line("annotated type did not work", p_subscript->base->datatype.type_source);
|
|
|
|
|
|
|
|
const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
|
|
const GDScriptParser::IdentifierNode *identifier_node = static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base);
|
|
|
|
|
|
@@ -3192,22 +3163,15 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c
|
|
is_function = true;
|
|
is_function = true;
|
|
[[fallthrough]];
|
|
[[fallthrough]];
|
|
case GDScriptParser::COMPLETION_ATTRIBUTE: {
|
|
case GDScriptParser::COMPLETION_ATTRIBUTE: {
|
|
- print_line("completion attribute");
|
|
|
|
- if (completion_context.base != nullptr) {
|
|
|
|
- print_line("base", completion_context.base->to_string());
|
|
|
|
- } else {
|
|
|
|
- print_line("no base");
|
|
|
|
- }
|
|
|
|
r_forced = true;
|
|
r_forced = true;
|
|
const GDScriptParser::SubscriptNode *attr = static_cast<const GDScriptParser::SubscriptNode *>(completion_context.node);
|
|
const GDScriptParser::SubscriptNode *attr = static_cast<const GDScriptParser::SubscriptNode *>(completion_context.node);
|
|
if (attr->base) {
|
|
if (attr->base) {
|
|
GDScriptCompletionIdentifier base;
|
|
GDScriptCompletionIdentifier base;
|
|
bool found_type = _get_subscript_type(completion_context, attr, base.type);
|
|
bool found_type = _get_subscript_type(completion_context, attr, base.type);
|
|
- print_line("found through subscript type", found_type);
|
|
|
|
if (!found_type && !_guess_expression_type(completion_context, attr->base, base)) {
|
|
if (!found_type && !_guess_expression_type(completion_context, attr->base, base)) {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- print_line(base.type.script_path, base.type.kind);
|
|
|
|
|
|
+
|
|
_find_identifiers_in_base(base, is_function, false, options, 0);
|
|
_find_identifiers_in_base(base, is_function, false, options, 0);
|
|
}
|
|
}
|
|
} break;
|
|
} break;
|