Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.2] C#: Add Visual Studio support #39784

Merged
merged 3 commits into from
Jun 26, 2020

Conversation

neikeq
Copy link
Contributor

@neikeq neikeq commented Jun 23, 2020

Backport of #39578 and #39783 to 3.2.

Sometimes Visual Studio documents have the root path all in upper case.
Since Godot doesn't support loading resource files with a case insensitive path,
this makes script resource loading to fail when the Godot editor gets code
completion requests from Visual Studio.
This fix allows the resource path part of the path to be case insensitive. It
still doesn't support cases where the rest of the path is also case insensitive.
For that we would need a proper API for comparing paths. However, this fix
should be enough for our current cases.
@akien-mga
Copy link
Member

Tested by merging the PR locally on 3.2, with an up-to-date VS 2019 and the addin installed from https://github.com/godotengine/godot-csharp-visualstudio/releases/tag/v1.1

Setup works fine and then it seems to work out of the box, so kudos!

Features described in the addin's readme seem functional ("Play in editor", documentation, code completion).

I did experience a few crashes of Godot when using it on a simple test project though. I haven't figured out exact steps to reproduce yet, but here's what I did when it crashed:

Crash 1

  • Load project in Godot and VS
  • Edit script, intentionally make syntax error (e.g. omit ;)
  • Build fails, cancel the tooltip that proposes to run the old build
  • Fix error, save, "Play in editor" -> editor builds, then crashes.

Error output:

Running: C:\Dev\Godot\godot.git\bin\godot.windows.tools.64.mono.exe --path C:/Users/Remi/Mono-Test --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 6796 --position 3088,375
ERROR: godot_icall_GD_pusherror: Unhandled exception in the peer loop
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
  at System.Net.Sockets.NetworkStream.EndRead (System.IAsyncResult asyncResult) [0x00015] in <829e0c1453fc48a1af6cbdc7ef2e8cf4>:0
  at System.IO.Stream+<>c.<BeginEndReadAsync>b__45_1 (System.IO.Stream stream, System.IAsyncResult asyncResult) [0x00000] in <d68b9accd7c7479a89d9a85470a20582>:0
  at System.Threading.Tasks.TaskFactory`1+FromAsyncTrimPromise`1[TResult,TInstance].Complete (TInstance thisRef, System.Func`3[T1,T2,TResult] endMethod, System.IAsyncResult asyncResult, System.Boolean requiresSynchronization) [0x00000] in <d68b9accd7c7479a89d9a85470a20582>:0
--- End of stack trace from previous location where exception was thrown ---

  at System.IO.StreamReader.ReadBufferAsync () [0x001e0] in <d68b9accd7c7479a89d9a85470a20582>:0
  at System.IO.StreamReader.ReadLineAsyncInternal () [0x00093] in <d68b9accd7c7479a89d9a85470a20582>:0
  at GodotTools.IdeMessaging.Peer.ReadLine () [0x000b0] in <22b1cc7a6c9542d4958cd3d1d92a6515>:0
  at GodotTools.IdeMessaging.Peer.Process () [0x0033a] in <22b1cc7a6c9542d4958cd3d1d92a6515>:0
   At: modules\mono\glue\gd_glue.cpp:250

Unhandled Exception:
System.NullReferenceException: Object reference not set to an instance of an object
  at System.Text.RegularExpressions.RegexCharClass..cctor () [0x00f88] in <829e0c1453fc48a1af6cbdc7ef2e8cf4>:0
  at System.Text.RegularExpressions.RegexCharClass..cctor () [0x00f6b] in <829e0c1453fc48a1af6cbdc7ef2e8cf4>:0
  at System.Text.RegularExpressions.RegexCharClass..cctor () [0x00f35] in <829e0c1453fc48a1af6cbdc7ef2e8cf4>:0
  at System.Text.RegularExpressions.RegexCharClass..cctor () [0x00e9c] in <829e0c1453fc48a1af6cbdc7ef2e8cf4>:0
  at System.Threading.Thread.StartInternal (System.Object principal, System.Threading.StackCrawlMark& stackMark) [0x00006] in <d68b9accd7c7479a89d9a85470a20582>:0
  at (wrapper managed-to-native) Godot.NativeCalls.godot_icall_0_3(intptr,intptr)
Running: C:\Dev\Godot\godot.git\bin\godot.windows.tools.64.mono.exe --path C:/Users/Remi/Mono-Test --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 6796 --position 3088,375
ERROR: GDMonoUtils::debug_send_unhandled_exception_error: System.NullReferenceException: Object reference not set to an instance of an object
   At: modules\mono\mono_gd\gd_mono_utils.cpp:371
Godot Engine v3.2.2.rc.mono.custom_build.1b47131e6 - https://godotengine.org
OpenGL ES 3.0 Renderer: Intel(R) HD Graphics 630

Mono: Logfile is: C:\Users\Remi\AppData\Roaming/Godot/mono/mono_logs/2020_06_24 14.54.32 (6952).txt
debugger-agent: Unable to connect to 127.0.0.1:8890

Crash 2

I then tried to reproduce it with the same steps. It didn't crash, so then I kept doing this:

  • Trivial edit to the script (with or without syntax error)
  • Hit "Play in editor"
    • If I made a syntax error, fix it, save and retry
    • Half of the time, VS would go in "play" mode but nothing would actually happen in Godot. After a few seconds, VS goes back in edit mode and I can retry.
  • Rince and repeat, eventually I got Godot to crash again with a different error:
Running: C:\Dev\Godot\godot.git\bin\godot.windows.tools.64.mono.exe --path C:/Users/Remi/Mono-Test --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 10076 --position 448,240
Running: C:\Dev\Godot\godot.git\bin\godot.windows.tools.64.mono.exe --path C:/Users/Remi/Mono-Test --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 10076 --position 3088,375
Running: C:\Dev\Godot\godot.git\bin\godot.windows.tools.64.mono.exe --path C:/Users/Remi/Mono-Test --remote-debug 127.0.0.1:6007 --allow_focus_steal_pid 10076 --position 3088,375
ERROR: godot_icall_GD_pusherror: Message handler for 'Request | DebugPlay' failed with exception
System.Threading.ThreadAbortException: Thread was being aborted.
  at Newtonsoft.Json.Serialization.DefaultContractResolver.IsJsonPrimitiveType (System.Type t) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x00007] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) [0x00034] in <d68b9accd7c7479a89d9a85470a20582>:0
  at Newtonsoft.Json.Utilities.ThreadSafeStore`2[TKey,TValue].Get (TKey key) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x0000b] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContract (System.Type type) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe (System.Type type) [0x0000b] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x0000e] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00054] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <2676a2da6edc420e890ed28aa4572ee5>:0
  at GodotTools.Ides.MessagingServer+ServerMessageHandler+<>c.<InitializeRequestHandlers>b__3_1 (GodotTools.IdeMessaging.Peer peer, GodotTools.IdeMessaging.MessageContent content) [0x0001b] in <d9755bc35e7a47ff8e7acfa27ff86752>:0
  at GodotTools.Ides.MessagingServer+ServerMessageHandler.HandleRequest (GodotTools.IdeMessaging.Peer peer, System.String id, GodotTools.IdeMessaging.MessageContent content, GodotTools.IdeMessaging.ILogger logger) [0x000d3] in <d9755bc35e7a47ff8e7acfa27ff86752>:0
  at GodotTools.IdeMessaging.Peer.Process () [0x0011d] in <22b1cc7a6c9542d4958cd3d1d92a6515>:0
   At: modules\mono\glue\gd_glue.cpp:250
ERROR: godot_icall_GD_pusherror: Unhandled exception in the peer loop
System.ObjectDisposedException: Cannot read from a closed TextReader.
  at System.IO.StreamReader.ReadLineAsync () [0x00026] in <d68b9accd7c7479a89d9a85470a20582>:0
  at GodotTools.IdeMessaging.Peer.ReadLine () [0x000b0] in <22b1cc7a6c9542d4958cd3d1d92a6515>:0
  at GodotTools.IdeMessaging.Peer.Process () [0x0033a] in <22b1cc7a6c9542d4958cd3d1d92a6515>:0
   At: modules\mono\glue\gd_glue.cpp:250

@neikeq
Copy link
Contributor Author

neikeq commented Jun 25, 2020

@akien-mga I wasn't able to reproduce the crashes. Perhaps it's caused by domain unloading. Do you have the native backtrace for all threads? (I'm particularly interested in the main thread)

Half of the time, VS would go in "play" mode but nothing would actually happen in Godot. After a few seconds, VS goes back in edit mode and I can retry.

This is a known bug in my list. It happens because after VS builds the project, Godot reloads the domain before it can receive the DebugPlay request from VS, so the request goes ignored.
This bug is not introduced in this PR. The same happens with MonoDevelop/VSMac since the beginning (although I only found about it recently).

This must have been missed when backporting the new protocol to 3.2.
@GeorgeS2019
Copy link

GeorgeS2019 commented Jun 26, 2020

Tested by merging the PR locally on 3.2, with an up-to-date VS 2019 and the addin installed from https://github.com/godotengine/godot-csharp-visualstudio/releases/tag/v1.1

Setup works fine and then it seems to work out of the box, so kudos!

Features described in the addin's readme seem functional ("Play in editor", documentation, code completion).

@akien-mga & @neikeq
Same, I use the latest 3.2 and repeated as above. It works out of box.

I recommend that we merge this to 3.2.2 soon so more people get to test to speed up the bugs identification and features improvement

@akien-mga
Copy link
Member

3.2.2-stable is released already, but yes, this is now ready to merge for 3.2.3.

@akien-mga akien-mga merged commit d6ff55f into godotengine:3.2 Jun 26, 2020
@akien-mga
Copy link
Member

Thanks!

@GeorgeS2019
Copy link

GeorgeS2019 commented Jun 29, 2020

@akien-mga I have testing the Visual Studio Support. It makes learning GodotSharp Tool environment a lot more easier, and other important .NET5 features e.g. SDK style project.

REF Godot Proposal: Support multiple .NET5 SDK style projects per godot project

@neikeq neikeq deleted the 3.2-visualstudio-support branch May 13, 2021 23:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants