| 3095 | } |
| 3096 | |
| 3097 | void ResourceFormatLoaderGDScript::get_classes_used(const String &p_path, HashSet<StringName> *r_classes) { |
| 3098 | Ref<GDScript> scr = ResourceLoader::load(p_path); |
| 3099 | if (scr.is_null()) { |
| 3100 | return; |
| 3101 | } |
| 3102 | |
| 3103 | const String source = scr->get_source_code(); |
| 3104 | GDScriptTokenizerText tokenizer; |
| 3105 | tokenizer.set_source_code(source); |
| 3106 | GDScriptTokenizer::Token current = tokenizer.scan(); |
| 3107 | while (current.type != GDScriptTokenizer::Token::TK_EOF) { |
| 3108 | if (!current.is_identifier()) { |
| 3109 | current = tokenizer.scan(); |
| 3110 | continue; |
| 3111 | } |
| 3112 | |
| 3113 | int insert_idx = 0; |
| 3114 | for (int i = 0; i < current.start_line - 1; i++) { |
| 3115 | insert_idx = source.find("\n", insert_idx) + 1; |
| 3116 | } |
| 3117 | // Insert the "cursor" character, needed for the lookup to work. |
| 3118 | const String source_with_cursor = source.insert(insert_idx + current.start_column, String::chr(0xFFFF)); |
| 3119 | |
| 3120 | ScriptLanguage::LookupResult result; |
| 3121 | if (scr->get_language()->lookup_code(source_with_cursor, current.get_identifier(), p_path, nullptr, result) == OK) { |
| 3122 | if (!result.class_name.is_empty() && ClassDB::class_exists(result.class_name)) { |
| 3123 | r_classes->insert(result.class_name); |
| 3124 | } |
| 3125 | |
| 3126 | if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_PROPERTY) { |
| 3127 | PropertyInfo prop; |
| 3128 | if (ClassDB::get_property_info(result.class_name, result.class_member, &prop)) { |
| 3129 | if (!prop.class_name.is_empty() && ClassDB::class_exists(prop.class_name)) { |
| 3130 | r_classes->insert(prop.class_name); |
| 3131 | } |
| 3132 | if (!prop.hint_string.is_empty() && ClassDB::class_exists(prop.hint_string)) { |
| 3133 | r_classes->insert(prop.hint_string); |
| 3134 | } |
| 3135 | } |
| 3136 | } else if (result.type == ScriptLanguage::LOOKUP_RESULT_CLASS_METHOD) { |
| 3137 | MethodInfo met; |
| 3138 | if (ClassDB::get_method_info(result.class_name, result.class_member, &met)) { |
| 3139 | if (!met.return_val.class_name.is_empty() && ClassDB::class_exists(met.return_val.class_name)) { |
| 3140 | r_classes->insert(met.return_val.class_name); |
| 3141 | } |
| 3142 | if (!met.return_val.hint_string.is_empty() && ClassDB::class_exists(met.return_val.hint_string)) { |
| 3143 | r_classes->insert(met.return_val.hint_string); |
| 3144 | } |
| 3145 | } |
| 3146 | } |
| 3147 | } |
| 3148 | |
| 3149 | current = tokenizer.scan(); |
| 3150 | } |
| 3151 | } |
| 3152 | |
| 3153 | Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags) { |
| 3154 | Ref<GDScript> sqscr = p_resource; |
nothing calls this directly
no test coverage detected