-Code completion for enumerations
-Disabled GDNative and GDNativeScript so build compiles again
This commit is contained in:
parent
3d1c031871
commit
36e0a72c77
|
@ -598,14 +598,23 @@ void ClassDB::bind_integer_constant(const StringName &p_class, const StringName
|
|||
|
||||
type->constant_map[p_name] = p_constant;
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
List<StringName> *constants_list = type->enum_map.getptr(p_enum);
|
||||
|
||||
if (constants_list) {
|
||||
constants_list->push_back(p_name);
|
||||
} else {
|
||||
List<StringName> new_list;
|
||||
new_list.push_back(p_name);
|
||||
type->enum_map[p_enum] = new_list;
|
||||
String enum_name = p_enum;
|
||||
if (enum_name!=String()) {
|
||||
if (enum_name.find(".")!=-1) {
|
||||
enum_name=enum_name.get_slicec('.',1);
|
||||
}
|
||||
|
||||
List<StringName> *constants_list = type->enum_map.getptr(enum_name);
|
||||
|
||||
if (constants_list) {
|
||||
constants_list->push_back(p_name);
|
||||
} else {
|
||||
List<StringName> new_list;
|
||||
new_list.push_back(p_name);
|
||||
type->enum_map[enum_name] = new_list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type->constant_order.push_back(p_name);
|
||||
|
|
|
@ -207,7 +207,7 @@ public:
|
|||
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const = 0;
|
||||
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
|
||||
|
||||
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; }
|
||||
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
|
||||
|
||||
struct LookupResult {
|
||||
enum Type {
|
||||
|
|
|
@ -1036,8 +1036,9 @@ void CodeTextEditor::_complete_request() {
|
|||
List<String> entries;
|
||||
String ctext = text_editor->get_text_for_completion();
|
||||
_code_complete_script(ctext, &entries);
|
||||
bool forced = false;
|
||||
if (code_complete_func) {
|
||||
code_complete_func(code_complete_ud, ctext, &entries);
|
||||
code_complete_func(code_complete_ud, ctext, &entries, forced);
|
||||
}
|
||||
// print_line("COMPLETE: "+p_request);
|
||||
if (entries.size() == 0)
|
||||
|
@ -1050,7 +1051,7 @@ void CodeTextEditor::_complete_request() {
|
|||
strs[i++] = E->get();
|
||||
}
|
||||
|
||||
text_editor->code_complete(strs);
|
||||
text_editor->code_complete(strs, forced);
|
||||
}
|
||||
|
||||
void CodeTextEditor::_font_resize_timeout() {
|
||||
|
@ -1267,6 +1268,7 @@ CodeTextEditor::CodeTextEditor() {
|
|||
cs.push_back(".");
|
||||
cs.push_back(",");
|
||||
cs.push_back("(");
|
||||
cs.push_back("=");
|
||||
cs.push_back("$");
|
||||
text_editor->set_completion(true, cs);
|
||||
idle->connect("timeout", this, "_text_changed_idle_timeout");
|
||||
|
|
|
@ -186,7 +186,7 @@ public:
|
|||
FindReplaceDialog();
|
||||
};
|
||||
|
||||
typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options);
|
||||
typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options, bool &r_forced);
|
||||
|
||||
class CodeTextEditor : public VBoxContainer {
|
||||
|
||||
|
|
|
@ -602,13 +602,13 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options) {
|
||||
void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force) {
|
||||
|
||||
ScriptTextEditor *ste = (ScriptTextEditor *)p_ud;
|
||||
ste->_code_complete_script(p_code, r_options);
|
||||
ste->_code_complete_script(p_code, r_options, r_force);
|
||||
}
|
||||
|
||||
void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options) {
|
||||
void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options, bool &r_force) {
|
||||
|
||||
if (color_panel->is_visible_in_tree()) return;
|
||||
Node *base = get_tree()->get_edited_scene_root();
|
||||
|
@ -616,7 +616,7 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<String>
|
|||
base = _find_node_for_script(base, base, script);
|
||||
}
|
||||
String hint;
|
||||
Error err = script->get_language()->complete_code(p_code, script->get_path().get_base_dir(), base, r_options, hint);
|
||||
Error err = script->get_language()->complete_code(p_code, script->get_path().get_base_dir(), base, r_options, r_force, hint);
|
||||
if (hint != "") {
|
||||
code_editor->get_text_edit()->set_code_hint(hint);
|
||||
}
|
||||
|
|
|
@ -94,12 +94,12 @@ class ScriptTextEditor : public ScriptEditorBase {
|
|||
};
|
||||
|
||||
protected:
|
||||
static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options);
|
||||
static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force);
|
||||
void _breakpoint_toggled(int p_row);
|
||||
|
||||
//no longer virtual
|
||||
void _validate_script();
|
||||
void _code_complete_script(const String &p_code, List<String> *r_options);
|
||||
void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force);
|
||||
void _load_theme_settings();
|
||||
|
||||
void _notification(int p_what);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
|
||||
def can_build(platform):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "editor/editor_settings.h"
|
||||
#include "gd_compiler.h"
|
||||
#include "gd_script.h"
|
||||
#include "global_constants.h"
|
||||
#include "os/file_access.h"
|
||||
#include "project_settings.h"
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -355,6 +356,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na
|
|||
|
||||
struct GDCompletionIdentifier {
|
||||
|
||||
String enumeration;
|
||||
StringName obj_type;
|
||||
Ref<GDScript> script;
|
||||
Variant::Type type;
|
||||
|
@ -608,7 +610,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
|
|||
|
||||
#ifdef TOOLS_ENABLED
|
||||
MethodBind *mb = ClassDB::get_method(base.obj_type, id);
|
||||
PropertyInfo pi = mb->get_argument_info(-1);
|
||||
PropertyInfo pi = mb->get_return_info();
|
||||
|
||||
//try calling the function if constant and all args are constant, should not crash..
|
||||
Object *baseptr = base.value;
|
||||
|
@ -809,6 +811,32 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
|
|||
|
||||
if (p1.value.get_type() == Variant::OBJECT) {
|
||||
//??
|
||||
if (p1.obj_type != StringName() && p2.type == Variant::STRING) {
|
||||
StringName index = p2.value;
|
||||
bool valid;
|
||||
Variant::Type t = ClassDB::get_property_type(p1.obj_type, index, &valid);
|
||||
if (t != Variant::NIL && valid) {
|
||||
r_type.type = t;
|
||||
if (t == Variant::INT) {
|
||||
//check for enum!
|
||||
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
|
||||
|
||||
StringName getter = ClassDB::get_property_getter(p1.obj_type, index);
|
||||
if (getter != StringName()) {
|
||||
MethodBind *mb = ClassDB::get_method(p1.obj_type, getter);
|
||||
if (mb) {
|
||||
PropertyInfo rt = mb->get_return_info();
|
||||
if (rt.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
r_type.enumeration = rt.class_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (p1.value.get_type() != Variant::NIL) {
|
||||
|
||||
bool valid;
|
||||
|
@ -908,6 +936,22 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_
|
|||
Variant::Type t = ClassDB::get_property_type(gdi.obj_type, p_identifier, &valid);
|
||||
if (t != Variant::NIL && valid) {
|
||||
r_type.type = t;
|
||||
if (t == Variant::INT) {
|
||||
//check for enum!
|
||||
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
|
||||
|
||||
StringName getter = ClassDB::get_property_getter(gdi.obj_type, p_identifier);
|
||||
if (getter != StringName()) {
|
||||
MethodBind *mb = ClassDB::get_method(gdi.obj_type, getter);
|
||||
if (mb) {
|
||||
PropertyInfo rt = mb->get_return_info();
|
||||
if (rt.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
r_type.enumeration = rt.class_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1436,7 +1480,7 @@ void get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_lis
|
|||
}
|
||||
}
|
||||
|
||||
static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, String &arghint) {
|
||||
static void _find_type_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, const StringName &p_method, const GDCompletionIdentifier &id, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
|
||||
|
||||
//print_line("find type arguments?");
|
||||
if (id.type == Variant::OBJECT && id.obj_type != StringName()) {
|
||||
|
@ -1642,8 +1686,43 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
}
|
||||
|
||||
} else {
|
||||
//regular method
|
||||
//regular method
|
||||
|
||||
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
|
||||
if (p_argidx < m->get_argument_count()) {
|
||||
PropertyInfo pi = m->get_argument_info(p_argidx);
|
||||
|
||||
if (pi.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
String enumeration = pi.class_name;
|
||||
if (enumeration.find(".") != -1) {
|
||||
//class constant
|
||||
List<StringName> constants;
|
||||
String cls = enumeration.get_slice(".", 0);
|
||||
String enm = enumeration.get_slice(".", 1);
|
||||
|
||||
ClassDB::get_enum_constants(cls, enm, &constants);
|
||||
//constants.sort_custom<StringName::AlphCompare>();
|
||||
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
|
||||
String add = cls + "." + E->get();
|
||||
result.insert(add);
|
||||
r_forced = true;
|
||||
}
|
||||
} else {
|
||||
|
||||
//global constant
|
||||
StringName current_enum = enumeration;
|
||||
|
||||
for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
|
||||
if (GlobalConstants::get_global_constant_enum(i) == current_enum) {
|
||||
result.insert(GlobalConstants::get_global_constant_name(i));
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
//global
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (p_method.operator String() == "connect" || (p_method.operator String() == "emit_signal" && p_argidx == 0)) {
|
||||
|
||||
if (p_argidx == 0) {
|
||||
|
@ -1664,6 +1743,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
|
||||
for (List<MethodInfo>::Element *E = sigs.front(); E; E = E->next()) {
|
||||
result.insert("\"" + E->get().name + "\"");
|
||||
r_forced = true;
|
||||
}
|
||||
|
||||
} else if (p_argidx == 2) {
|
||||
|
@ -1671,6 +1751,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
if (context._class) {
|
||||
for (int i = 0; i < context._class->functions.size(); i++) {
|
||||
result.insert("\"" + context._class->functions[i]->name + "\"");
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1696,6 +1777,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
//print_line("found "+s);
|
||||
String name = s.get_slice("/", 1);
|
||||
result.insert("\"/root/" + name + "\"");
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1707,11 +1789,12 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
for (List<String>::Element *E = options.front(); E; E = E->next()) {
|
||||
|
||||
result.insert(E->get());
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arghint = _get_visual_datatype(m->get_argument_info(-1), false) + " " + p_method.operator String() + String("(");
|
||||
arghint = _get_visual_datatype(m->get_return_info(), false) + " " + p_method.operator String() + String("(");
|
||||
|
||||
for (int i = 0; i < m->get_argument_count(); i++) {
|
||||
if (i > 0)
|
||||
|
@ -1750,7 +1833,7 @@ static void _find_type_arguments(GDCompletionContext &context, const GDParser::N
|
|||
}
|
||||
}
|
||||
|
||||
static void _find_call_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, String &arghint) {
|
||||
static void _find_call_arguments(GDCompletionContext &context, const GDParser::Node *p_node, int p_line, int p_argidx, Set<String> &result, bool &r_forced, String &arghint) {
|
||||
|
||||
if (!p_node || p_node->type != GDParser::Node::TYPE_OPERATOR) {
|
||||
|
||||
|
@ -1905,7 +1988,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
|
|||
if (!context._class->owner)
|
||||
ci.value = context.base;
|
||||
|
||||
_find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, arghint);
|
||||
_find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, r_forced, arghint);
|
||||
//guess type..
|
||||
/*
|
||||
List<MethodInfo> methods;
|
||||
|
@ -1927,7 +2010,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
|
|||
GDCompletionIdentifier ci;
|
||||
if (_guess_expression_type(context, op->arguments[0], p_line, ci)) {
|
||||
|
||||
_find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, arghint);
|
||||
_find_type_arguments(context, p_node, p_line, id->name, ci, p_argidx, result, r_forced, arghint);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2027,14 +2110,14 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
|
|||
#endif
|
||||
}
|
||||
|
||||
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) {
|
||||
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
|
||||
|
||||
GDParser p;
|
||||
|
||||
p.parse(p_code, p_base_path, false, "", true);
|
||||
bool isfunction = false;
|
||||
Set<String> options;
|
||||
|
||||
r_forced = false;
|
||||
GDCompletionContext context;
|
||||
context._class = p.get_completion_class();
|
||||
context.block = p.get_completion_block();
|
||||
|
@ -2073,6 +2156,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
|
|||
|
||||
String opt = E->get().strip_edges();
|
||||
if (opt.begins_with("\"") && opt.ends_with("\"")) {
|
||||
r_forced = true;
|
||||
String idopt = opt.substr(1, opt.length() - 2);
|
||||
if (idopt.replace("/", "_").is_valid_identifier()) {
|
||||
options.insert(idopt);
|
||||
|
@ -2297,7 +2381,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
|
|||
} break;
|
||||
case GDParser::COMPLETION_CALL_ARGUMENTS: {
|
||||
|
||||
_find_call_arguments(context, p.get_completion_node(), p.get_completion_line(), p.get_completion_argument_index(), options, r_call_hint);
|
||||
_find_call_arguments(context, p.get_completion_node(), p.get_completion_line(), p.get_completion_argument_index(), options, r_forced, r_call_hint);
|
||||
} break;
|
||||
case GDParser::COMPLETION_VIRTUAL_FUNC: {
|
||||
|
||||
|
@ -2344,6 +2428,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
|
|||
ClassDB::get_signal_list(t.obj_type, &sigs);
|
||||
for (List<MethodInfo>::Element *E = sigs.front(); E; E = E->next()) {
|
||||
options.insert("\"" + E->get().name + "\"");
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2353,6 +2438,42 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_base
|
|||
if (EditorSettings::get_singleton()->get("text_editor/completion/complete_file_paths"))
|
||||
get_directory_contents(EditorFileSystem::get_singleton()->get_filesystem(), options);
|
||||
} break;
|
||||
case GDParser::COMPLETION_ASSIGN: {
|
||||
#if defined(DEBUG_METHODS_ENABLED) && defined(TOOLS_ENABLED)
|
||||
|
||||
GDCompletionIdentifier ci;
|
||||
if (_guess_expression_type(context, p.get_completion_node(), p.get_completion_line(), ci)) {
|
||||
|
||||
String enumeration = ci.enumeration;
|
||||
if (enumeration.find(".") != -1) {
|
||||
//class constant
|
||||
List<StringName> constants;
|
||||
String cls = enumeration.get_slice(".", 0);
|
||||
String enm = enumeration.get_slice(".", 1);
|
||||
|
||||
ClassDB::get_enum_constants(cls, enm, &constants);
|
||||
//constants.sort_custom<StringName::AlphCompare>();
|
||||
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
|
||||
String add = cls + "." + E->get();
|
||||
r_options->push_back(add);
|
||||
r_forced = true;
|
||||
}
|
||||
} else {
|
||||
|
||||
//global constant
|
||||
StringName current_enum = enumeration;
|
||||
|
||||
for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
|
||||
if (GlobalConstants::get_global_constant_enum(i) == current_enum) {
|
||||
r_options->push_back(GlobalConstants::get_global_constant_name(i));
|
||||
r_forced = true;
|
||||
}
|
||||
}
|
||||
//global
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
}
|
||||
|
||||
for (Set<String>::Element *E = options.front(); E; E = E->next()) {
|
||||
|
|
|
@ -1044,6 +1044,7 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
|
|||
return NULL; \
|
||||
} \
|
||||
p_allow_assign = false;
|
||||
|
||||
switch (tokenizer->get_token()) { //see operator
|
||||
|
||||
case GDTokenizer::TK_OP_IN: op = OperatorNode::OP_IN; break;
|
||||
|
@ -1065,7 +1066,22 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool
|
|||
//case GDTokenizer::TK_OP_NEG: op=OperatorNode::OP_NEG ; break;
|
||||
case GDTokenizer::TK_OP_SHIFT_LEFT: op = OperatorNode::OP_SHIFT_LEFT; break;
|
||||
case GDTokenizer::TK_OP_SHIFT_RIGHT: op = OperatorNode::OP_SHIFT_RIGHT; break;
|
||||
case GDTokenizer::TK_OP_ASSIGN: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN; break;
|
||||
case GDTokenizer::TK_OP_ASSIGN: {
|
||||
_VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN;
|
||||
|
||||
if (tokenizer->get_token(1) == GDTokenizer::TK_CURSOR) {
|
||||
//code complete assignment
|
||||
completion_type = COMPLETION_ASSIGN;
|
||||
completion_node = expr;
|
||||
completion_class = current_class;
|
||||
completion_function = current_function;
|
||||
completion_line = tokenizer->get_token_line();
|
||||
completion_block = current_block;
|
||||
completion_found = true;
|
||||
tokenizer->advance();
|
||||
}
|
||||
|
||||
} break;
|
||||
case GDTokenizer::TK_OP_ASSIGN_ADD: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_ADD; break;
|
||||
case GDTokenizer::TK_OP_ASSIGN_SUB: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_SUB; break;
|
||||
case GDTokenizer::TK_OP_ASSIGN_MUL: _VALIDATE_ASSIGN op = OperatorNode::OP_ASSIGN_MUL; break;
|
||||
|
|
|
@ -441,6 +441,7 @@ public:
|
|||
COMPLETION_INDEX,
|
||||
COMPLETION_VIRTUAL_FUNC,
|
||||
COMPLETION_YIELD,
|
||||
COMPLETION_ASSIGN,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -390,7 +390,7 @@ public:
|
|||
virtual int find_function(const String &p_function, const String &p_code) const;
|
||||
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
|
||||
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return OK; }
|
||||
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint);
|
||||
virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result);
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
|
||||
def can_build(platform):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
|
|
@ -4319,6 +4319,7 @@ void TextEdit::_cancel_completion() {
|
|||
return;
|
||||
|
||||
completion_active = false;
|
||||
completion_forced = false;
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -4386,13 +4387,19 @@ void TextEdit::_update_completion_candidates() {
|
|||
}
|
||||
}
|
||||
|
||||
if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) {
|
||||
if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_forced) {
|
||||
cancel = true;
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
if (cancel || (!pre_keyword && s == "" && (cofs == 0 || !completion_prefixes.has(String::chr(l[cofs - 1]))))) {
|
||||
bool prev_is_prefix = false;
|
||||
if (cofs > 0 && completion_prefixes.has(String::chr(l[cofs - 1])))
|
||||
prev_is_prefix = true;
|
||||
if (cofs > 1 && l[cofs - 1] == ' ' && completion_prefixes.has(String::chr(l[cofs - 2]))) //check with one space before prefix, to allow indent
|
||||
prev_is_prefix = true;
|
||||
|
||||
if (cancel || (!pre_keyword && s == "" && (cofs == 0 || !prev_is_prefix))) {
|
||||
//none to complete, cancel
|
||||
_cancel_completion();
|
||||
return;
|
||||
|
@ -4481,6 +4488,8 @@ void TextEdit::query_code_comple() {
|
|||
|
||||
if (ofs > 0 && (inquote || _is_completable(l[ofs - 1]) || completion_prefixes.has(String::chr(l[ofs - 1]))))
|
||||
emit_signal("request_completion");
|
||||
else if (ofs > 1 && l[ofs - 1] == ' ' && completion_prefixes.has(String::chr(l[ofs - 2]))) //make it work with a space too, it's good enough
|
||||
emit_signal("request_completion");
|
||||
}
|
||||
|
||||
void TextEdit::set_code_hint(const String &p_hint) {
|
||||
|
@ -4492,12 +4501,13 @@ void TextEdit::set_code_hint(const String &p_hint) {
|
|||
update();
|
||||
}
|
||||
|
||||
void TextEdit::code_complete(const Vector<String> &p_strings) {
|
||||
void TextEdit::code_complete(const Vector<String> &p_strings, bool p_forced) {
|
||||
|
||||
VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1);
|
||||
raised_from_completion = true;
|
||||
completion_strings = p_strings;
|
||||
completion_active = true;
|
||||
completion_forced = p_forced;
|
||||
completion_current = "";
|
||||
completion_index = 0;
|
||||
_update_completion_candidates();
|
||||
|
|
|
@ -205,6 +205,7 @@ class TextEdit : public Control {
|
|||
Vector<String> completion_strings;
|
||||
Vector<String> completion_options;
|
||||
bool completion_active;
|
||||
bool completion_forced;
|
||||
String completion_current;
|
||||
String completion_base;
|
||||
int completion_index;
|
||||
|
@ -522,7 +523,7 @@ public:
|
|||
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
|
||||
|
||||
void set_completion(bool p_enabled, const Vector<String> &p_prefixes);
|
||||
void code_complete(const Vector<String> &p_strings);
|
||||
void code_complete(const Vector<String> &p_strings, bool p_forced = false);
|
||||
void set_code_hint(const String &p_hint);
|
||||
void query_code_comple();
|
||||
|
||||
|
|
Loading…
Reference in New Issue