Browse Source

Merge pull request #23336 from neikeq/dd

Fix C# parsing the full name of base types
Ignacio Etcheverry 6 years ago
parent
commit
aeddb30fa3

+ 1 - 0
modules/mono/editor/csharp_project.cpp

@@ -167,6 +167,7 @@ Error generate_scripts_metadata(const String &p_project_path, const String &p_ou
 		ScriptClassParser scp;
 		ScriptClassParser scp;
 		Error err = scp.parse_file(project_file);
 		Error err = scp.parse_file(project_file);
 		if (err != OK) {
 		if (err != OK) {
+			ERR_PRINTS("Parse error: " + scp.get_error());
 			ERR_EXPLAIN("Failed to determine namespace and class for script: " + project_file);
 			ERR_EXPLAIN("Failed to determine namespace and class for script: " + project_file);
 			ERR_FAIL_V(err);
 			ERR_FAIL_V(err);
 		}
 		}

+ 96 - 40
modules/mono/editor/script_class_parser.cpp

@@ -5,6 +5,30 @@
 
 
 #include "../utils/string_utils.h"
 #include "../utils/string_utils.h"
 
 
+const char *ScriptClassParser::token_names[ScriptClassParser::TK_MAX] = {
+	"[",
+	"]",
+	"{",
+	"}",
+	".",
+	":",
+	",",
+	"Symbol",
+	"Identifier",
+	"String",
+	"Number",
+	"<",
+	">",
+	"EOF",
+	"Error"
+};
+
+String ScriptClassParser::get_token_name(ScriptClassParser::Token p_token) {
+
+	ERR_FAIL_INDEX_V(p_token, TK_MAX, "<error>");
+	return token_names[p_token];
+}
+
 ScriptClassParser::Token ScriptClassParser::get_token() {
 ScriptClassParser::Token ScriptClassParser::get_token() {
 
 
 	while (true) {
 	while (true) {
@@ -203,7 +227,7 @@ ScriptClassParser::Token ScriptClassParser::get_token() {
 	}
 	}
 }
 }
 
 
-Error ScriptClassParser::_skip_type_parameters() {
+Error ScriptClassParser::_skip_generic_type_params() {
 
 
 	Token tk;
 	Token tk;
 
 
@@ -213,68 +237,100 @@ Error ScriptClassParser::_skip_type_parameters() {
 		if (tk == TK_IDENTIFIER) {
 		if (tk == TK_IDENTIFIER) {
 			tk = get_token();
 			tk = get_token();
 
 
+			if (tk == TK_PERIOD) {
+				while (true) {
+					tk = get_token();
+
+					if (tk != TK_IDENTIFIER) {
+						error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
+						error = true;
+						return ERR_PARSE_ERROR;
+					}
+
+					tk = get_token();
+
+					if (tk != TK_PERIOD)
+						break;
+				}
+			}
+
 			if (tk == TK_OP_LESS) {
 			if (tk == TK_OP_LESS) {
-				Error err = _skip_type_parameters();
+				Error err = _skip_generic_type_params();
 				if (err)
 				if (err)
 					return err;
 					return err;
 				continue;
 				continue;
 			} else if (tk != TK_COMMA) {
 			} else if (tk != TK_COMMA) {
-				error_str = "Unexpected token: " + itos(tk);
+				error_str = "Unexpected token: " + get_token_name(tk);
 				error = true;
 				error = true;
 				return ERR_PARSE_ERROR;
 				return ERR_PARSE_ERROR;
 			}
 			}
 		} else if (tk == TK_OP_LESS) {
 		} else if (tk == TK_OP_LESS) {
-			error_str = "Expected identifier before `<`.";
+			error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found " + get_token_name(TK_OP_LESS);
 			error = true;
 			error = true;
 			return ERR_PARSE_ERROR;
 			return ERR_PARSE_ERROR;
 		} else if (tk == TK_OP_GREATER) {
 		} else if (tk == TK_OP_GREATER) {
 			return OK;
 			return OK;
 		} else {
 		} else {
-			error_str = "Unexpected token: " + itos(tk);
+			error_str = "Unexpected token: " + get_token_name(tk);
 			error = true;
 			error = true;
 			return ERR_PARSE_ERROR;
 			return ERR_PARSE_ERROR;
 		}
 		}
 	}
 	}
 }
 }
 
 
-Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
+Error ScriptClassParser::_parse_type_full_name(String &r_full_name) {
 
 
-	Token tk;
+	Token tk = get_token();
 
 
-	while (true) {
-		tk = get_token();
+	if (tk != TK_IDENTIFIER) {
+		error_str = "Expected " + get_token_name(TK_IDENTIFIER) + ", found: " + get_token_name(tk);
+		error = true;
+		return ERR_PARSE_ERROR;
+	}
 
 
-		if (tk == TK_IDENTIFIER) {
-			bool generic = false;
+	r_full_name += String(value);
 
 
-			String name = value;
+	if (code[idx] != '.') // We only want to take the next token if it's a period
+		return OK;
 
 
-			tk = get_token();
+	tk = get_token();
 
 
-			if (tk == TK_OP_LESS) {
-				generic = true;
-				Error err = _skip_type_parameters();
-				if (err)
-					return err;
-			} else if (tk == TK_COMMA) {
-				Error err = _parse_class_base(r_base);
-				if (err)
-					return err;
-			} else if (tk != TK_CURLY_BRACKET_OPEN) {
-				error_str = "Unexpected token: " + itos(tk);
-				error = true;
-				return ERR_PARSE_ERROR;
-			}
+	CRASH_COND(tk != TK_PERIOD); // Assertion
 
 
-			r_base.push_back(!generic ? name : String()); // no generics, please
+	r_full_name += ".";
 
 
-			return OK;
-		} else {
-			error_str = "Unexpected token: " + itos(tk);
-			error = true;
-			return ERR_PARSE_ERROR;
-		}
+	return _parse_type_full_name(r_full_name);
+}
+
+Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
+
+	String name;
+
+	Error err = _parse_type_full_name(name);
+	if (err)
+		return err;
+
+	Token tk = get_token();
+
+	if (tk == TK_OP_LESS) {
+		// We don't add it to the base list if it's generic
+		Error err = _skip_generic_type_params();
+		if (err)
+			return err;
+	} else if (tk == TK_COMMA) {
+		Error err = _parse_class_base(r_base);
+		if (err)
+			return err;
+		r_base.push_back(name);
+	} else if (tk == TK_CURLY_BRACKET_OPEN) {
+		r_base.push_back(name);
+	} else {
+		error_str = "Unexpected token: " + get_token_name(tk);
+		error = true;
+		return ERR_PARSE_ERROR;
 	}
 	}
+
+	return OK;
 }
 }
 
 
 Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
 Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
@@ -284,7 +340,7 @@ Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stac
 	if (tk == TK_IDENTIFIER) {
 	if (tk == TK_IDENTIFIER) {
 		r_name += String(value);
 		r_name += String(value);
 	} else {
 	} else {
-		error_str = "Unexpected token: " + itos(tk);
+		error_str = "Unexpected token: " + get_token_name(tk);
 		error = true;
 		error = true;
 		return ERR_PARSE_ERROR;
 		return ERR_PARSE_ERROR;
 	}
 	}
@@ -298,7 +354,7 @@ Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stac
 		r_curly_stack++;
 		r_curly_stack++;
 		return OK;
 		return OK;
 	} else {
 	} else {
-		error_str = "Unexpected token: " + itos(tk);
+		error_str = "Unexpected token: " + get_token_name(tk);
 		error = true;
 		error = true;
 		return ERR_PARSE_ERROR;
 		return ERR_PARSE_ERROR;
 	}
 	}
@@ -366,11 +422,11 @@ Error ScriptClassParser::parse(const String &p_code) {
 					} else if (tk == TK_OP_LESS && !generic) {
 					} else if (tk == TK_OP_LESS && !generic) {
 						generic = true;
 						generic = true;
 
 
-						Error err = _skip_type_parameters();
+						Error err = _skip_generic_type_params();
 						if (err)
 						if (err)
 							return err;
 							return err;
 					} else {
 					} else {
-						error_str = "Unexpected token: " + itos(tk);
+						error_str = "Unexpected token: " + get_token_name(tk);
 						error = true;
 						error = true;
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
@@ -400,7 +456,7 @@ Error ScriptClassParser::parse(const String &p_code) {
 					name = String(value);
 					name = String(value);
 				} else if (tk == TK_CURLY_BRACKET_OPEN) {
 				} else if (tk == TK_CURLY_BRACKET_OPEN) {
 					if (name.empty()) {
 					if (name.empty()) {
-						error_str = "Expected identifier after keyword `struct`. Found `{`.";
+						error_str = "Expected " + get_token_name(TK_IDENTIFIER) + " after keyword `struct`, found " + get_token_name(TK_CURLY_BRACKET_OPEN);
 						error = true;
 						error = true;
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
@@ -409,7 +465,7 @@ Error ScriptClassParser::parse(const String &p_code) {
 					type_curly_stack++;
 					type_curly_stack++;
 					break;
 					break;
 				} else if (tk == TK_EOF) {
 				} else if (tk == TK_EOF) {
-					error_str = "Expected `{` after struct decl. Found `EOF`.";
+					error_str = "Expected " + get_token_name(TK_CURLY_BRACKET_OPEN) + " after struct decl, found " + get_token_name(TK_EOF);
 					error = true;
 					error = true;
 					return ERR_PARSE_ERROR;
 					return ERR_PARSE_ERROR;
 				}
 				}

+ 7 - 2
modules/mono/editor/script_class_parser.h

@@ -52,13 +52,18 @@ private:
 		TK_OP_LESS,
 		TK_OP_LESS,
 		TK_OP_GREATER,
 		TK_OP_GREATER,
 		TK_EOF,
 		TK_EOF,
-		TK_ERROR
+		TK_ERROR,
+		TK_MAX
 	};
 	};
 
 
+	static const char *token_names[TK_MAX];
+	static String get_token_name(Token p_token);
+
 	Token get_token();
 	Token get_token();
 
 
-	Error _skip_type_parameters();
+	Error _skip_generic_type_params();
 
 
+	Error _parse_type_full_name(String &r_full_name);
 	Error _parse_class_base(Vector<String> &r_base);
 	Error _parse_class_base(Vector<String> &r_base);
 	Error _parse_namespace_name(String &r_name, int &r_curly_stack);
 	Error _parse_namespace_name(String &r_name, int &r_curly_stack);