mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	-Code completion for enumerations
-Disabled GDNative and GDNativeScript so build compiles again
This commit is contained in:
		
							parent
							
								
									3d1c031871
								
							
						
					
					
						commit
						36e0a72c77
					
				
					 14 changed files with 195 additions and 35 deletions
				
			
		|  | @ -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()) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Juan Linietsky
						Juan Linietsky