summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgnacio Etcheverry <neikeq@users.noreply.github.com>2018-11-25 17:05:04 +0100
committerGitHub <noreply@github.com>2018-11-25 17:05:04 +0100
commit95d604b9cdde554a4e3ede796791827eb33e3196 (patch)
treef0167970dd82feca05d4c38e9c0167dc39d0c252
parent0d69da8c0ec1df3d8486208a45979187b97d56ec (diff)
parentd339824f154074454a783a4a2a517199df2d7c35 (diff)
Merge pull request #23515 from cart/fix-mono-parse
Parse C# generics and type constraints correctly
-rw-r--r--modules/mono/editor/GodotSharpTools/.gitignore2
-rw-r--r--modules/mono/editor/script_class_parser.cpp101
-rw-r--r--modules/mono/editor/script_class_parser.h1
3 files changed, 100 insertions, 4 deletions
diff --git a/modules/mono/editor/GodotSharpTools/.gitignore b/modules/mono/editor/GodotSharpTools/.gitignore
new file mode 100644
index 0000000000..296ad48834
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/.gitignore
@@ -0,0 +1,2 @@
+# nuget packages
+packages \ No newline at end of file
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
index bc8eed81cf..9042bff74a 100644
--- a/modules/mono/editor/script_class_parser.cpp
+++ b/modules/mono/editor/script_class_parser.cpp
@@ -259,6 +259,8 @@ Error ScriptClassParser::_skip_generic_type_params() {
if (err)
return err;
continue;
+ } else if (tk == TK_OP_GREATER) {
+ return OK;
} else if (tk != TK_COMMA) {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
@@ -312,27 +314,108 @@ Error ScriptClassParser::_parse_class_base(Vector<String> &r_base) {
Token tk = get_token();
+ bool generic = false;
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) {
+ // We don't add it to the base list if it's generic
+ generic = true;
+ tk = get_token();
+ }
+
+ if (tk == TK_COMMA) {
Error err = _parse_class_base(r_base);
if (err)
return err;
- r_base.push_back(name);
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ Error err = _parse_type_constraints();
+ if (err) {
+ return err;
+ }
+
+ // An open curly bracket was parsed by _parse_type_constraints, so we can exit
} else if (tk == TK_CURLY_BRACKET_OPEN) {
- r_base.push_back(name);
+ // we are finished when we hit the open curly bracket
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
return ERR_PARSE_ERROR;
}
+ if (!generic) {
+ r_base.push_back(name);
+ }
+
return OK;
}
+Error ScriptClassParser::_parse_type_constraints() {
+ Token tk = get_token();
+ if (tk != TK_IDENTIFIER) {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = get_token();
+ if (tk != TK_COLON) {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+
+ while (true) {
+ tk = get_token();
+ if (tk == TK_IDENTIFIER) {
+ if (String(value) == "where") {
+ return _parse_type_constraints();
+ }
+
+ 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_COMMA) {
+ continue;
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ return _parse_type_constraints();
+ } else if (tk == TK_SYMBOL && String(value) == "(") {
+ tk = get_token();
+ if (tk != TK_SYMBOL || String(value) != ")") {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk == TK_OP_LESS) {
+ Error err = _skip_generic_type_params();
+ if (err)
+ return err;
+ } else if (tk == TK_CURLY_BRACKET_OPEN) {
+ return OK;
+ } else {
+ error_str = "Unexpected token: " + get_token_name(tk);
+ error = true;
+ return ERR_PARSE_ERROR;
+ }
+ }
+}
+
Error ScriptClassParser::_parse_namespace_name(String &r_name, int &r_curly_stack) {
Token tk = get_token();
@@ -425,6 +508,16 @@ Error ScriptClassParser::parse(const String &p_code) {
Error err = _skip_generic_type_params();
if (err)
return err;
+ } else if (tk == TK_IDENTIFIER && String(value) == "where") {
+ Error err = _parse_type_constraints();
+ if (err) {
+ return err;
+ }
+
+ // An open curly bracket was parsed by _parse_type_constraints, so we can exit
+ curly_stack++;
+ type_curly_stack++;
+ break;
} else {
error_str = "Unexpected token: " + get_token_name(tk);
error = true;
diff --git a/modules/mono/editor/script_class_parser.h b/modules/mono/editor/script_class_parser.h
index 1e174c28a9..184adebaf2 100644
--- a/modules/mono/editor/script_class_parser.h
+++ b/modules/mono/editor/script_class_parser.h
@@ -65,6 +65,7 @@ private:
Error _parse_type_full_name(String &r_full_name);
Error _parse_class_base(Vector<String> &r_base);
+ Error _parse_type_constraints();
Error _parse_namespace_name(String &r_name, int &r_curly_stack);
public: