summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/io/multiplayer_api.cpp1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs7
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs11
-rw-r--r--modules/mono/editor/script_class_parser.cpp81
-rw-r--r--modules/websocket/websocket_multiplayer_peer.cpp2
5 files changed, 97 insertions, 5 deletions
diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp
index 2708cb8c01..381ac4c0bb 100644
--- a/core/io/multiplayer_api.cpp
+++ b/core/io/multiplayer_api.cpp
@@ -111,6 +111,7 @@ void MultiplayerAPI::poll() {
Error err = network_peer->get_packet(&packet, len);
if (err != OK) {
ERR_PRINT("Error getting packet!");
+ break; // Something is wrong!
}
rpc_sender_id = sender;
diff --git a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
index 174509dc5b..9abfda4538 100644
--- a/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/CsProjOperations.cs
@@ -81,7 +81,12 @@ namespace GodotTools
}
}
- ScriptClassParser.ParseFileOrThrow(projectIncludeFile, out var classes);
+ Error parseError = ScriptClassParser.ParseFile(projectIncludeFile, out var classes, out string errorStr);
+ if (parseError != Error.Ok)
+ {
+ GD.PushError($"Failed to determine namespace and class for script: {projectIncludeFile}. Parse error: {errorStr ?? parseError.ToString()}");
+ continue;
+ }
string searchName = System.IO.Path.GetFileNameWithoutExtension(projectIncludeFile);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
index 11afa8773e..7fb087467f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/ScriptClassParser.cs
@@ -27,12 +27,15 @@ namespace GodotTools.Internals
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern Error internal_ParseFile(string filePath, Array<Dictionary> classes, out string errorStr);
- public static void ParseFileOrThrow(string filePath, out IEnumerable<ClassDecl> classes)
+ public static Error ParseFile(string filePath, out IEnumerable<ClassDecl> classes, out string errorStr)
{
var classesArray = new Array<Dictionary>();
- var error = internal_ParseFile(filePath, classesArray, out string errorStr);
+ var error = internal_ParseFile(filePath, classesArray, out errorStr);
if (error != Error.Ok)
- throw new Exception($"Failed to determine namespace and class for script: {filePath}. Parse error: {errorStr ?? error.ToString()}");
+ {
+ classes = null;
+ return error;
+ }
var classesList = new List<ClassDecl>();
@@ -47,6 +50,8 @@ namespace GodotTools.Internals
}
classes = classesList;
+
+ return Error.Ok;
}
}
}
diff --git a/modules/mono/editor/script_class_parser.cpp b/modules/mono/editor/script_class_parser.cpp
index 84163dd952..8ac4df9952 100644
--- a/modules/mono/editor/script_class_parser.cpp
+++ b/modules/mono/editor/script_class_parser.cpp
@@ -631,6 +631,85 @@ Error ScriptClassParser::parse(const String &p_code) {
return OK;
}
+static String get_preprocessor_directive(const String &p_line, int p_from) {
+ CRASH_COND(p_line[p_from] != '#');
+ p_from++;
+ int i = p_from;
+ while (i < p_line.length() && p_line[i] != ' ' && p_line[i] != '\t') {
+ i++;
+ }
+ return p_line.substr(p_from, i - p_from);
+}
+
+static void run_dummy_preprocessor(String &r_source) {
+
+ Vector<String> lines = r_source.split("\n", /* p_allow_empty: */ true);
+
+ bool *include_lines = memnew_arr(bool, lines.size());
+
+ int if_level = -1;
+ Vector<bool> is_branch_being_compiled;
+
+ for (int i = 0; i < lines.size(); i++) {
+ const String &line = lines[i];
+
+ const int line_len = line.length();
+
+ int j = 0;
+ while (j < line_len) {
+ if (line[j] != ' ' && line[j] != '\t') {
+ if (line[j] == '#') {
+ // First non-whitespace char of the line is '#'
+ include_lines[i] = false;
+
+ String directive = get_preprocessor_directive(line, j);
+
+ if (directive == "if") {
+ if_level++;
+ is_branch_being_compiled.push_back(if_level == 0 || is_branch_being_compiled[if_level - 1]);
+ } else if (directive == "elif") {
+ ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#elif' directive.");
+ is_branch_being_compiled.write[if_level] = false;
+ } else if (directive == "else") {
+ ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#else' directive.");
+ is_branch_being_compiled.write[if_level] = false;
+ } else if (directive == "endif") {
+ ERR_CONTINUE_MSG(if_level == -1, "Found unexpected '#endif' directive.");
+ is_branch_being_compiled.remove(if_level);
+ if_level--;
+ }
+
+ break;
+ } else {
+ // First non-whitespace char of the line is not '#'
+ include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
+ break;
+ }
+ }
+
+ j++;
+ }
+
+ if (j == line_len) {
+ // Loop ended without finding a non-whitespace character.
+ // Either the line was empty or it only contained whitespaces.
+ include_lines[i] = if_level == -1 || is_branch_being_compiled[if_level];
+ }
+ }
+
+ r_source.clear();
+
+ // Custom join ignoring lines removed by the preprocessor
+ for (int i = 0; i < lines.size(); i++) {
+ if (i > 0 && include_lines[i - 1])
+ r_source += '\n';
+
+ if (include_lines[i]) {
+ r_source += lines[i];
+ }
+ }
+}
+
Error ScriptClassParser::parse_file(const String &p_filepath) {
String source;
@@ -643,6 +722,8 @@ Error ScriptClassParser::parse_file(const String &p_filepath) {
" Please ensure that scripts are saved in valid UTF-8 unicode." :
"Failed to read file: '" + p_filepath + "'.");
+ run_dummy_preprocessor(source);
+
return parse(source);
}
diff --git a/modules/websocket/websocket_multiplayer_peer.cpp b/modules/websocket/websocket_multiplayer_peer.cpp
index b639c635fd..27ea50b524 100644
--- a/modules/websocket/websocket_multiplayer_peer.cpp
+++ b/modules/websocket/websocket_multiplayer_peer.cpp
@@ -98,7 +98,7 @@ void WebSocketMultiplayerPeer::_bind_methods() {
//
int WebSocketMultiplayerPeer::get_available_packet_count() const {
- ERR_FAIL_COND_V_MSG(!_is_multiplayer, ERR_UNCONFIGURED, "Please use get_peer(ID).get_available_packet_count to get available packet count from peers when not using the MultiplayerAPI.");
+ ERR_FAIL_COND_V_MSG(!_is_multiplayer, 0, "Please use get_peer(ID).get_available_packet_count to get available packet count from peers when not using the MultiplayerAPI.");
return _incoming_packets.size();
}