mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 21:51:22 +00:00 
			
		
		
		
	Merge pull request #72444 from reduz/fix-global-class-parsing
Fix global script class parsing.
This commit is contained in:
		
						commit
						e768e02b78
					
				
					 2 changed files with 83 additions and 13 deletions
				
			
		|  | @ -2437,22 +2437,26 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b | ||||||
| 
 | 
 | ||||||
| 	GDScriptParser parser; | 	GDScriptParser parser; | ||||||
| 	err = parser.parse(source, p_path, false); | 	err = parser.parse(source, p_path, false); | ||||||
| 	if (err) { |  | ||||||
| 		return String(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	GDScriptAnalyzer analyzer(&parser); |  | ||||||
| 	err = analyzer.resolve_inheritance(); |  | ||||||
| 	if (err) { |  | ||||||
| 		return String(); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	const GDScriptParser::ClassNode *c = parser.get_tree(); | 	const GDScriptParser::ClassNode *c = parser.get_tree(); | ||||||
| 
 | 	if (!c) { | ||||||
| 	if (r_base_type) { | 		return String(); // No class parsed.
 | ||||||
| 		*r_base_type = c->get_datatype().native_type; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/* **WARNING**
 | ||||||
|  | 	 * | ||||||
|  | 	 * This function is written with the goal to be *extremely* error tolerant, as such | ||||||
|  | 	 * it should meet the following requirements: | ||||||
|  | 	 * | ||||||
|  | 	 * - It must not rely on the analyzer (in fact, the analyzer must not be used here), | ||||||
|  | 	 *   because at the time global classes are parsed, the dependencies may not be present | ||||||
|  | 	 *   yet, hence the function will fail (which is unintended). | ||||||
|  | 	 * - It must not fail even if the parsing fails, because even if the file is broken, | ||||||
|  | 	 *   it should attempt its best to retrieve the inheritance metadata. | ||||||
|  | 	 * | ||||||
|  | 	 * Before changing this function, please ask the current maintainer of EditorFileSystem. | ||||||
|  | 	 */ | ||||||
|  | 
 | ||||||
| 	if (r_icon_path) { | 	if (r_icon_path) { | ||||||
| 		if (c->icon_path.is_empty() || c->icon_path.is_absolute_path()) { | 		if (c->icon_path.is_empty() || c->icon_path.is_absolute_path()) { | ||||||
| 			*r_icon_path = c->icon_path.simplify_path(); | 			*r_icon_path = c->icon_path.simplify_path(); | ||||||
|  | @ -2460,7 +2464,73 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b | ||||||
| 			*r_icon_path = p_path.get_base_dir().path_join(c->icon_path).simplify_path(); | 			*r_icon_path = p_path.get_base_dir().path_join(c->icon_path).simplify_path(); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	if (r_base_type) { | ||||||
|  | 		const GDScriptParser::ClassNode *subclass = c; | ||||||
|  | 		String path = p_path; | ||||||
|  | 		GDScriptParser subparser; | ||||||
|  | 		while (subclass) { | ||||||
|  | 			if (subclass->extends_used) { | ||||||
|  | 				if (!subclass->extends_path.is_empty()) { | ||||||
|  | 					if (subclass->extends.size() == 0) { | ||||||
|  | 						get_global_class_name(subclass->extends_path, r_base_type); | ||||||
|  | 						subclass = nullptr; | ||||||
|  | 						break; | ||||||
|  | 					} else { | ||||||
|  | 						Vector<StringName> extend_classes = subclass->extends; | ||||||
| 
 | 
 | ||||||
|  | 						Ref<FileAccess> subfile = FileAccess::open(subclass->extends_path, FileAccess::READ); | ||||||
|  | 						if (subfile.is_null()) { | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						String subsource = subfile->get_as_utf8_string(); | ||||||
|  | 
 | ||||||
|  | 						if (subsource.is_empty()) { | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						String subpath = subclass->extends_path; | ||||||
|  | 						if (subpath.is_relative_path()) { | ||||||
|  | 							subpath = path.get_base_dir().path_join(subpath).simplify_path(); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
|  | 						if (OK != subparser.parse(subsource, subpath, false)) { | ||||||
|  | 							break; | ||||||
|  | 						} | ||||||
|  | 						path = subpath; | ||||||
|  | 						subclass = subparser.get_tree(); | ||||||
|  | 
 | ||||||
|  | 						while (extend_classes.size() > 0) { | ||||||
|  | 							bool found = false; | ||||||
|  | 							for (int i = 0; i < subclass->members.size(); i++) { | ||||||
|  | 								if (subclass->members[i].type != GDScriptParser::ClassNode::Member::CLASS) { | ||||||
|  | 									continue; | ||||||
|  | 								} | ||||||
|  | 
 | ||||||
|  | 								const GDScriptParser::ClassNode *inner_class = subclass->members[i].m_class; | ||||||
|  | 								if (inner_class->identifier->name == extend_classes[0]) { | ||||||
|  | 									extend_classes.remove_at(0); | ||||||
|  | 									found = true; | ||||||
|  | 									subclass = inner_class; | ||||||
|  | 									break; | ||||||
|  | 								} | ||||||
|  | 							} | ||||||
|  | 							if (!found) { | ||||||
|  | 								subclass = nullptr; | ||||||
|  | 								break; | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} else if (subclass->extends.size() == 1) { | ||||||
|  | 					*r_base_type = subclass->extends[0]; | ||||||
|  | 					subclass = nullptr; | ||||||
|  | 				} else { | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				*r_base_type = "RefCounted"; | ||||||
|  | 				subclass = nullptr; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 	return c->identifier != nullptr ? String(c->identifier->name) : String(); | 	return c->identifier != nullptr ? String(c->identifier->name) : String(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| # Error here. Annotations should be used before `class_name`, not after. | # Error here. Annotations should be used before `class_name`, not after. | ||||||
| class_name HelloWorld | class_name WrongAnnotationPlace | ||||||
| @icon("res://path/to/optional/icon.svg") | @icon("res://path/to/optional/icon.svg") | ||||||
| 
 | 
 | ||||||
| func test(): | func test(): | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Rémi Verschelde
						Rémi Verschelde