├── Publish.txt ├── External ├── CorApi.dll ├── CorApi2.dll ├── Mono.Cairo.dll ├── Mono.Cecil.dll ├── Mono.Posix.dll ├── atk-sharp.dll ├── gdk-sharp.dll ├── glib-sharp.dll ├── gtk-sharp.dll ├── Mono.Addins.dll ├── pango-sharp.dll ├── Mono.Cecil.Mdb.dll ├── Mono.Cecil.Pdb.dll ├── Mono.Debugging.dll ├── Newtonsoft.Json.dll ├── Mono.Cecil.Rocks.dll ├── Mono.Debugger.Soft.dll ├── MonoDevelop.Unity.dll ├── Mono.Debugging.Soft.dll ├── Mono.Debugging.Win32.dll ├── MonoDevelop.Debugger.dll ├── ICSharpCode.NRefactory.dll ├── MonoDevelop.Debugger.Soft.dll ├── ICSharpCode.NRefactory.Cecil.dll ├── System.Collections.Immutable.dll ├── System.Reflection.Metadata.dll ├── ICSharpCode.NRefactory.CSharp.dll ├── System.Composition.Convention.dll ├── System.Composition.AttributedModel.dll ├── MonoDevelop.Debugger.VsCodeDebugProtocol.dll ├── SyntaxTree.VisualStudio.Unity.Messaging.dll └── Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.dll ├── Images ├── dark │ ├── Unity.png │ └── stage.svg ├── plus-128.png ├── new-file-tb.png ├── stage.svg ├── light │ └── stage.svg ├── plus.svg └── plus-round.svg ├── Screenshots ├── vscode-debug-view.png ├── vscode-debugger-list.png └── vscode-debugger-unity.png ├── TestApp ├── TestEvaluation2.cs ├── packages.config ├── Properties │ └── AssemblyInfo.cs ├── Main.cs ├── NonUserCodeClass.cs ├── TestApp.csproj └── AdvancedEvaluation.cs ├── AppDomainClient ├── packages.config ├── Client.cs ├── Properties │ └── AssemblyInfo.cs └── AppDomainClient.csproj ├── Tests ├── AppDomainClient │ ├── packages.config │ ├── Client.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── AppDomainClient.csproj ├── UnityDebug.Tests │ ├── packages.config │ ├── IMDTextFile.cs │ ├── MDLogger.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SdbBreakpointsAndSteppingTests.cs │ ├── CorBreakpointsAndSteppingTests.cs │ ├── SdbEvaluationTests.cs │ ├── SdbStackFrameTests.cs │ ├── CorStackFrameTests.cs │ ├── CorEvaluationTests.cs │ ├── TextFile.cs │ ├── CodeCompletionTests.cs │ ├── ITextFile.cs │ ├── StackFrameTests.cs │ ├── UnityDebug.Tests.csproj │ ├── AdvancedEvaluationTests.cs │ ├── DebugTests.cs │ └── MDTextFile.cs ├── NonUserCodeTestLib │ ├── packages.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── NonUserCodeClass.cs │ └── NonUserCodeTestLib.csproj ├── PlayerConnectionTests │ ├── packages.config │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── PlayerConnectionTests.csproj │ └── PlayerConnection.cs └── UnityDebug.Tests.TestApp │ ├── packages.config │ ├── TestApp.csproj.user │ ├── Properties │ └── AssemblyInfo.cs │ ├── Main.cs │ ├── UnityDebug.Tests.TestApp.csproj │ └── AdvancedEvaluation.cs ├── UnityDebug ├── app.config ├── Util.cs ├── Properties │ └── AssemblyInfo.cs ├── Platform.cs ├── Log.cs ├── Program.cs ├── UnityAttach.cs └── UnityDebug.csproj ├── .gitignore ├── typescript ├── tsconfig.json ├── attach.ts └── exceptions.ts ├── .vscodeignore ├── Makefile ├── .gitmodules ├── .vscode ├── launch.json └── tasks.json ├── LICENSE.txt ├── issue_template.md ├── webpack.config.js ├── README.md ├── CHANGELOG.md └── package.json /Publish.txt: -------------------------------------------------------------------------------- 1 | https://marketplace.visualstudio.com/manage -------------------------------------------------------------------------------- /External/CorApi.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/CorApi.dll -------------------------------------------------------------------------------- /External/CorApi2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/CorApi2.dll -------------------------------------------------------------------------------- /Images/dark/Unity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Images/dark/Unity.png -------------------------------------------------------------------------------- /Images/plus-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Images/plus-128.png -------------------------------------------------------------------------------- /External/Mono.Cairo.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Cairo.dll -------------------------------------------------------------------------------- /External/Mono.Cecil.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Cecil.dll -------------------------------------------------------------------------------- /External/Mono.Posix.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Posix.dll -------------------------------------------------------------------------------- /External/atk-sharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/atk-sharp.dll -------------------------------------------------------------------------------- /External/gdk-sharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/gdk-sharp.dll -------------------------------------------------------------------------------- /External/glib-sharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/glib-sharp.dll -------------------------------------------------------------------------------- /External/gtk-sharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/gtk-sharp.dll -------------------------------------------------------------------------------- /Images/new-file-tb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Images/new-file-tb.png -------------------------------------------------------------------------------- /External/Mono.Addins.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Addins.dll -------------------------------------------------------------------------------- /External/pango-sharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/pango-sharp.dll -------------------------------------------------------------------------------- /External/Mono.Cecil.Mdb.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Cecil.Mdb.dll -------------------------------------------------------------------------------- /External/Mono.Cecil.Pdb.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Cecil.Pdb.dll -------------------------------------------------------------------------------- /External/Mono.Debugging.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Debugging.dll -------------------------------------------------------------------------------- /External/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /External/Mono.Cecil.Rocks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Cecil.Rocks.dll -------------------------------------------------------------------------------- /External/Mono.Debugger.Soft.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Debugger.Soft.dll -------------------------------------------------------------------------------- /External/MonoDevelop.Unity.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/MonoDevelop.Unity.dll -------------------------------------------------------------------------------- /External/Mono.Debugging.Soft.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Debugging.Soft.dll -------------------------------------------------------------------------------- /External/Mono.Debugging.Win32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Mono.Debugging.Win32.dll -------------------------------------------------------------------------------- /External/MonoDevelop.Debugger.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/MonoDevelop.Debugger.dll -------------------------------------------------------------------------------- /Screenshots/vscode-debug-view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Screenshots/vscode-debug-view.png -------------------------------------------------------------------------------- /External/ICSharpCode.NRefactory.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/ICSharpCode.NRefactory.dll -------------------------------------------------------------------------------- /Screenshots/vscode-debugger-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Screenshots/vscode-debugger-list.png -------------------------------------------------------------------------------- /TestApp/TestEvaluation2.cs: -------------------------------------------------------------------------------- 1 | namespace TestApp 2 | { 3 | public class TestEvaluation2 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /External/MonoDevelop.Debugger.Soft.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/MonoDevelop.Debugger.Soft.dll -------------------------------------------------------------------------------- /Screenshots/vscode-debugger-unity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/Screenshots/vscode-debugger-unity.png -------------------------------------------------------------------------------- /External/ICSharpCode.NRefactory.Cecil.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/ICSharpCode.NRefactory.Cecil.dll -------------------------------------------------------------------------------- /External/System.Collections.Immutable.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/System.Collections.Immutable.dll -------------------------------------------------------------------------------- /External/System.Reflection.Metadata.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/System.Reflection.Metadata.dll -------------------------------------------------------------------------------- /External/ICSharpCode.NRefactory.CSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/ICSharpCode.NRefactory.CSharp.dll -------------------------------------------------------------------------------- /External/System.Composition.Convention.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/System.Composition.Convention.dll -------------------------------------------------------------------------------- /External/System.Composition.AttributedModel.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/System.Composition.AttributedModel.dll -------------------------------------------------------------------------------- /TestApp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /External/MonoDevelop.Debugger.VsCodeDebugProtocol.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/MonoDevelop.Debugger.VsCodeDebugProtocol.dll -------------------------------------------------------------------------------- /External/SyntaxTree.VisualStudio.Unity.Messaging.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/SyntaxTree.VisualStudio.Unity.Messaging.dll -------------------------------------------------------------------------------- /AppDomainClient/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/AppDomainClient/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/NonUserCodeTestLib/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/PlayerConnectionTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /External/Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deitry/vscode-unity-debug/HEAD/External/Microsoft.VisualStudio.Shared.VSCodeDebugProtocol.dll -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /UnityDebug/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Images/stage.svg: -------------------------------------------------------------------------------- 1 | Layer 1 -------------------------------------------------------------------------------- /Images/dark/stage.svg: -------------------------------------------------------------------------------- 1 | Layer 1 -------------------------------------------------------------------------------- /Images/light/stage.svg: -------------------------------------------------------------------------------- 1 | Layer 1 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | UnityDebug/obj 2 | bin 3 | *.zip 4 | *.vsix 5 | *.DotSettings.user 6 | .idea 7 | .vscode 8 | !.vscode/launch.json 9 | !.vscode/tasks.json 10 | .vs 11 | dist/ 12 | node_modules 13 | oldExternal 14 | out 15 | obj 16 | packages 17 | TODO 18 | temp 19 | -------------------------------------------------------------------------------- /typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "noImplicitAny": false, 6 | "removeComments": false, 7 | "preserveConstEnums": true, 8 | "target": "es5", 9 | "lib":["es6"], 10 | "outDir": "../out", 11 | "sourceMap": true 12 | } 13 | } -------------------------------------------------------------------------------- /AppDomainClient/Client.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | class Client 4 | { 5 | static int Main (string [] args) 6 | { 7 | int res = 0;/*c6632437-1cac-45db-ac15-0ca13cf02aa1*/ 8 | foreach (string s in args) { 9 | res += Convert.ToInt32 (s); 10 | } 11 | return res; 12 | } 13 | } -------------------------------------------------------------------------------- /Tests/AppDomainClient/Client.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | class Client 4 | { 5 | static int Main (string [] args) 6 | { 7 | int res = 0;/*c6632437-1cac-45db-ac15-0ca13cf02aa1*/ 8 | foreach (string s in args) { 9 | res += Convert.ToInt32 (s); 10 | } 11 | return res; 12 | } 13 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/TestApp.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | TestEvaluation 5 | 6 | -------------------------------------------------------------------------------- /UnityDebug/Util.cs: -------------------------------------------------------------------------------- 1 | namespace MonoDevelop.Debugger.Soft.Unity 2 | { 3 | public class Util 4 | { 5 | static Util() 6 | { 7 | UnityLocation = ""; 8 | UnityEditorDataFolder = ""; 9 | } 10 | 11 | public static string UnityLocation { get; set; } 12 | 13 | public static string UnityEditorDataFolder { get; set; } 14 | 15 | public static string FindUnity () 16 | { 17 | return string.Empty; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | **/.mdb 3 | *.vsix 4 | 5 | .git 6 | .idea 7 | .vscode 8 | .vs 9 | 10 | node_modules/ 11 | out/ 12 | packages/ 13 | 14 | AppDomainClient/ 15 | debugger-libs/ 16 | external/ 17 | MonoDebug/ 18 | MonoDevelop.Debugger.Soft.Unity/ 19 | nrefactory/ 20 | Screenshots/ 21 | TestApp/ 22 | Tests/ 23 | typescript/ 24 | UnityDebug/ 25 | 26 | Makefile 27 | package-lock.json 28 | Publish.txt 29 | VSCode-UnityDebug.sln* 30 | webpack.config.js -------------------------------------------------------------------------------- /Images/plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | UNITY_DEBUG = bin/UnityDebug.exe 2 | 3 | all: $UNITY_DEBUG 4 | 5 | clean: 6 | rm -rf bin/ 7 | xbuild /p:Configuration=Release /t:Clean 8 | 9 | $UNITY_DEBUG: 10 | xbuild /p:Configuration=Release 11 | 12 | build: 13 | tsc -p ./typescript 14 | @echo "build finished" 15 | 16 | zip: $UNITY_DEBUG 17 | rm -f unity-debug.zip 18 | zip -r9 unity-debug.zip bin/ attach.ts package.json Changelog.txt -x "*.DS_Store" 19 | 20 | vsix: clean $UNITY_DEBUG 21 | rm -f *.vsix 22 | vsce package -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/IMDTextFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Mono.Debugging.Tests { 4 | public interface IMDTextFile 5 | { 6 | string Name { get; } 7 | 8 | string Text { get; } 9 | int Length { get; } 10 | 11 | string GetText (int startPosition, int endPosition); 12 | char GetCharAt (int position); 13 | 14 | int GetPositionFromLineColumn (int line, int column); 15 | void GetLineColumnFromPosition (int position, out int line, out int column); 16 | } 17 | } -------------------------------------------------------------------------------- /Images/plus-round.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "MonoDebug"] 2 | path = MonoDebug 3 | url = https://github.com/deitry/vscode-mono-debug.git 4 | [submodule "MonoDevelop.Debugger.Soft.Unity"] 5 | path = MonoDevelop.Debugger.Soft.Unity 6 | url = https://github.com/Unity-Technologies/MonoDevelop.Debugger.Soft.Unity 7 | [submodule "debugger-libs"] 8 | path = debugger-libs 9 | url = https://github.com/deitry/debugger-libs.git 10 | [submodule "External/cecil"] 11 | path = External/cecil 12 | url = https://github.com/jbevain/cecil.git 13 | [submodule "nrefactory"] 14 | path = nrefactory 15 | url = https://github.com/icsharpcode/nrefactory 16 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Extension", 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "runtimeExecutable": "${execPath}", 9 | "args": [ 10 | "--extensionDevelopmentPath=${workspaceRoot}" 11 | ], 12 | "stopOnEntry": false, 13 | "sourceMaps": true, 14 | "outFiles": [ 15 | "${workspaceRoot}/dist/*.js" 16 | ], 17 | "preLaunchTask": "buildDev" 18 | }, 19 | { 20 | "name": "Attach to Debugger", 21 | "type": "clr", 22 | "request": "attach", 23 | "processName": "UnityDebug.exe", 24 | "justMyCode": false, 25 | "requireExactSource": false, 26 | "preLaunchTask": "Build all" 27 | } 28 | ] 29 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/MDLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Mono.Debugging.Client; 3 | 4 | namespace UnityDebug.Tests 5 | { 6 | public class MDLogger : ICustomLogger 7 | { 8 | public string GetNewDebuggerLogFilename () 9 | { 10 | return ""; 11 | } 12 | 13 | public void LogError (string message, Exception ex) 14 | { 15 | Console.Error.WriteLine(message); 16 | Console.Error.WriteLine(ex.Message); 17 | } 18 | 19 | public void LogAndShowException (string message, Exception ex) 20 | { 21 | LogError(message, ex); 22 | } 23 | 24 | public void LogMessage (string messageFormat, params object[] args) 25 | { 26 | Console.Out.WriteLine(messageFormat, args); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) Unity Technologies 2 | 3 | All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | -------------------------------------------------------------------------------- /UnityDebug/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle ("UnityDebug")] 8 | [assembly: AssemblyDescription ("Unity debug adapter for Visual Studio Code")] 9 | [assembly: AssemblyConfiguration ("")] 10 | [assembly: AssemblyCompany ("Unity Technologies")] 11 | [assembly: AssemblyProduct ("")] 12 | [assembly: AssemblyCopyright ("Unity Technologies")] 13 | [assembly: AssemblyTrademark ("")] 14 | [assembly: AssemblyCulture ("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion ("0.5.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | 28 | -------------------------------------------------------------------------------- /UnityDebug/Platform.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | 7 | namespace MonoDevelop.Debugger.Soft.Unity 8 | { 9 | public static class Platform 10 | { 11 | private const string OSASCRIPT = "/usr/bin/osascript"; // osascript is the AppleScript interpreter on OS X 12 | private const string LINUX_TERM = "/usr/bin/gnome-terminal"; //private const string LINUX_TERM = "/usr/bin/x-terminal-emulator"; 13 | 14 | /* 15 | * Is this Windows? 16 | */ 17 | public static bool IsWindows 18 | { 19 | get 20 | { 21 | var pid = Environment.OSVersion.Platform; 22 | return !(pid == PlatformID.Unix || pid == PlatformID.MacOSX); 23 | } 24 | } 25 | 26 | /* 27 | * Is this OS X? 28 | */ 29 | public static bool IsMac => File.Exists(OSASCRIPT); 30 | 31 | /* 32 | * Is this Linux? 33 | */ 34 | public static bool IsLinux => File.Exists(LINUX_TERM); 35 | 36 | public static bool IsLocal(string address) 37 | { 38 | try 39 | { 40 | if (address == "127.0.0.1") 41 | return true; 42 | return Dns.GetHostAddresses(Dns.GetHostName()).Any(ip => ip.ToString() == address); 43 | } 44 | catch 45 | { 46 | return false; 47 | } 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /issue_template.md: -------------------------------------------------------------------------------- 1 | Your issue may already be reported! 2 | Please search on the [issue track](https://github.com/Unity-Technologies/vscode-unity-debug/issues) before creating one. 3 | 4 | ## Expected Behavior 5 | 6 | 7 | 8 | ## Current Behavior 9 | 10 | 11 | 12 | ## Possible Solution 13 | 14 | 15 | 16 | ## Steps to Reproduce (for bugs) 17 | 18 | 19 | 1. 20 | 2. 21 | 3. 22 | 4. 23 | 24 | ## Context 25 | 26 | 27 | 28 | ## Your Environment 29 | * Unity Version: 30 | * VS Code Version: 31 | * Version of the debugger tool: 32 | * Operating System and version: 33 | 34 | -------------------------------------------------------------------------------- /UnityDebug/Log.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Security.AccessControl; 5 | using System.Text; 6 | 7 | namespace UnityDebug 8 | { 9 | public static class Log 10 | { 11 | static readonly string logPath; 12 | 13 | public static bool Debug { get; set; } 14 | 15 | static Log () 16 | { 17 | logPath = Path.Combine(Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location), Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly ().Location) + "-log.txt"); 18 | File.WriteAllText (logPath, FormatMessage("Log\n---\n")); 19 | } 20 | 21 | static string FormatMessage(string message) 22 | { 23 | var time = DateTime.Now.ToString ("HH:mm:ss.ffffff"); 24 | return $"{time}: {message}\n"; 25 | } 26 | 27 | public static void DebugWrite(string message) 28 | { 29 | if (Debug) 30 | Write (message); 31 | } 32 | 33 | public static void LogError(string message, Exception ex) 34 | { 35 | Write(message + (ex != null ? Environment.NewLine + ex : string.Empty)); 36 | } 37 | 38 | public static void Write(string message) 39 | { 40 | var formattedMessage = FormatMessage (message); 41 | var buf = Encoding.UTF8.GetBytes(formattedMessage); 42 | using (var stream = new FileStream(logPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite)) 43 | { 44 | stream.Write(buf, 0, buf.Length); 45 | } 46 | } 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | //@ts-check 2 | 3 | 'use strict'; 4 | 5 | const path = require('path'); 6 | 7 | /**@type {import('webpack').Configuration}*/ 8 | const config = { 9 | target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/ 10 | 11 | entry: './typescript/attach.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/ 12 | output: { 13 | // the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/ 14 | path: path.resolve(__dirname, 'dist'), 15 | filename: 'extension.js', 16 | libraryTarget: 'commonjs2', 17 | devtoolModuleFilenameTemplate: '../[resource-path]' 18 | }, 19 | devtool: 'source-map', 20 | externals: { 21 | vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/ 22 | }, 23 | resolve: { 24 | // support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader 25 | extensions: ['.ts', '.js'] 26 | }, 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.ts$/, 31 | exclude: /node_modules/, 32 | use: [ 33 | { 34 | loader: 'ts-loader' 35 | } 36 | ] 37 | } 38 | ] 39 | } 40 | }; 41 | module.exports = config; -------------------------------------------------------------------------------- /TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("TestApp")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("TestApp")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("E486F44C-C7A4-4CF1-8A17-69F0182C9E7E")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /AppDomainClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AppDomainClient")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("AppDomainClient")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("E671AE70-6384-41FF-8444-6DD967F117CD")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/AppDomainClient/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AppDomainClient")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("AppDomainClient")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("E671AE70-6384-41FF-8444-6DD967F117CD")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("UnityDebug.Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("UnityDebug.Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("33071BC3-C0E6-47F1-96CE-50BBCE820DD4")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/NonUserCodeTestLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("NonUserCodeTestLib")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("NonUserCodeTestLib")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("4FE265AA-4EFD-4891-B7E8-001FB76009C2")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/PlayerConnectionTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("PlayerConnectionTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("PlayerConnectionTests")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("13139A0F-0BD7-4771-ACE9-A567FCCD4C93")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("UnityDebug.Tests.TestApp")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("UnityDebug.Tests.TestApp")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("E486F44C-C7A4-4CF1-8A17-69F0182C9E7E")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/SdbBreakpointsAndSteppingTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // SdbBreakpointsAndSteppingTests.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using NUnit.Framework; 28 | 29 | namespace VSCode.UnityDebug.Tests.Soft 30 | { 31 | [TestFixture] 32 | public class SdbBreakpointsAndSteppingTests: BreakpointsAndSteppingTests 33 | { 34 | public SdbBreakpointsAndSteppingTests () : base ("Mono.Debugger.Soft") 35 | { 36 | } 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /TestApp/Main.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Main.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2009 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using System; 28 | using System.Collections; 29 | using System.Collections.Generic; 30 | using System.Diagnostics; 31 | 32 | namespace UnityDebug.TestApp 33 | { 34 | class MainClass 35 | { 36 | public static void Main (string[] args) 37 | { 38 | var test = Activator.CreateInstance (Type.GetType ("UnityDebug.TestApp." + args [0])); 39 | test.GetType().GetMethod ("RunTest").Invoke (null, null); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/Main.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Main.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2009 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using System; 28 | using System.Collections; 29 | using System.Collections.Generic; 30 | using System.Diagnostics; 31 | 32 | namespace UnityDebug.Tests.TestApp 33 | { 34 | class MainClass 35 | { 36 | public static void Main (string[] args) 37 | { 38 | var test = Activator.CreateInstance (Type.GetType ("UnityDebug.Tests.TestApp." + args [0])); 39 | test.GetType().GetMethod ("RunTest").Invoke (null, null); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/CorBreakpointsAndSteppingTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // CorBreakpointsAndSteppingTests.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2014 Xamarin, Inc (http://www.xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using Mono.Debugging.Client; 28 | using NUnit.Framework; 29 | using UnityDebug.Tests; 30 | 31 | namespace VSCode.UnityDebug.Tests.Win32 32 | { 33 | [TestFixture] 34 | [Platform (Include = "Win")] 35 | public class CorBreakpointsAndSteppingTests: BreakpointsAndSteppingTests 36 | { 37 | public CorBreakpointsAndSteppingTests () : base ("MonoDevelop.Debugger.Win32") 38 | { 39 | DebuggerLoggingService.CustomLogger = new MDLogger (); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/SdbEvaluationTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // SdbEvaluationTests.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2009 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using NUnit.Framework; 28 | 29 | namespace VSCode.UnityDebug.Tests.Soft 30 | { 31 | [TestFixture] 32 | public class SdbEvaluationAllowTargetInvokesTests: EvaluationTests 33 | { 34 | public SdbEvaluationAllowTargetInvokesTests (): base ("Mono.Debugger.Soft", true) 35 | { 36 | } 37 | } 38 | 39 | [TestFixture] 40 | public class SdbEvaluationNoTargetInvokesTests: EvaluationTests 41 | { 42 | public SdbEvaluationNoTargetInvokesTests (): base ("Mono.Debugger.Soft", false) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/SdbStackFrameTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // SdbStackFrameTests.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2010 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using NUnit.Framework; 28 | 29 | namespace VSCode.UnityDebug.Tests.Soft 30 | { 31 | [TestFixture] 32 | public class SdbStackFrameAllowTargetInvokesTests : StackFrameTests 33 | { 34 | public SdbStackFrameAllowTargetInvokesTests (): base ("Mono.Debugger.Soft", true) 35 | { 36 | } 37 | } 38 | 39 | [TestFixture] 40 | public class SdbStackFrameNoTargetInvokesTests : StackFrameTests 41 | { 42 | public SdbStackFrameNoTargetInvokesTests (): base ("Mono.Debugger.Soft", false) 43 | { 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/CorStackFrameTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // CorStackFrametests.cs 3 | // 4 | // Author: 5 | // Therzok 6 | // 7 | // Copyright (c) 2013 Xamarin Inc. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using NUnit.Framework; 27 | 28 | namespace VSCode.UnityDebug.Tests.Win32 29 | { 30 | [TestFixture] 31 | [Platform (Include = "Win")] 32 | public class CorStackFrameAllowTargetInvokesTests : StackFrameTests 33 | { 34 | public CorStackFrameAllowTargetInvokesTests (): base ("MonoDevelop.Debugger.Win32", true) 35 | { 36 | } 37 | } 38 | 39 | [TestFixture] 40 | [Platform (Include = "Win")] 41 | public class CorStackFrameNoTargetInvokesTests : StackFrameTests 42 | { 43 | public CorStackFrameNoTargetInvokesTests (): base ("MonoDevelop.Debugger.Win32", false) 44 | { 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/CorEvaluationTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // CorEvaluationTests.cs 3 | // 4 | // Author: 5 | // Therzok 6 | // 7 | // Copyright (c) 2013 Xamarin Inc. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using NUnit.Framework; 28 | 29 | namespace VSCode.UnityDebug.Tests.Win32 30 | { 31 | [TestFixture] 32 | [Platform (Include = "Win")] 33 | public class CorEvaluationAllowTargetInvokesTests: EvaluationTests 34 | { 35 | public CorEvaluationAllowTargetInvokesTests (): base ("MonoDevelop.Debugger.Win32", true) 36 | { 37 | } 38 | } 39 | 40 | [TestFixture] 41 | [Platform (Include = "Win")] 42 | public class CorEvaluationNoTargetInvokesTests: EvaluationTests 43 | { 44 | public CorEvaluationNoTargetInvokesTests (): base ("MonoDevelop.Debugger.Win32", false) 45 | { 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /TestApp/NonUserCodeClass.cs: -------------------------------------------------------------------------------- 1 | // 2 | // MyClass.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using System.Threading.Tasks; 28 | 29 | namespace MonoDevelop.Debugger.Tests.NonUserCodeTestLib 30 | { 31 | public class NonUserCodeClass 32 | { 33 | // Trick with NonUserCode is that we are referencing output.dll instead of project 34 | // in MonoDevelop.Debugger.Tests.TestApp. 35 | 36 | //We must delay exception so stacktrace is not getting back to user code(in TestApp) 37 | public static void ThrowDelayedHandledException () 38 | { 39 | Task.Delay (100).ContinueWith ((obj) => { 40 | try { 41 | throw new Exception ("3913936e-3f89-4f07-a863-7275aaaa5fc9"); 42 | } catch { 43 | } 44 | }); 45 | } 46 | 47 | public static void NonUserMethod() 48 | { 49 | new NonUserCodeClass();/*ce16b8fd-dd76-440e-886a-8278820ce908*/ 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/NonUserCodeTestLib/NonUserCodeClass.cs: -------------------------------------------------------------------------------- 1 | // 2 | // MyClass.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using System.Threading.Tasks; 28 | 29 | namespace UnityDebug.Tests.NonUserCodeTestLib 30 | { 31 | public class NonUserCodeClass 32 | { 33 | // Trick with NonUserCode is that we are referencing output.dll instead of project 34 | // in MonoDevelop.Debugger.Tests.UnityDebug.Tests.TestApp. 35 | 36 | //We must delay exception so stacktrace is not getting back to user code(in UnityDebug.Tests.TestApp) 37 | public static void ThrowDelayedHandledException () 38 | { 39 | Task.Delay (100).ContinueWith ((obj) => { 40 | try { 41 | throw new Exception ("3913936e-3f89-4f07-a863-7275aaaa5fc9"); 42 | } catch { 43 | } 44 | }); 45 | } 46 | 47 | public static void NonUserMethod() 48 | { 49 | new NonUserCodeClass();/*ce16b8fd-dd76-440e-886a-8278820ce908*/ 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/TextFile.cs: -------------------------------------------------------------------------------- 1 | namespace Mono.Debugging.Tests 2 | { 3 | public class TextFile : ITextFile 4 | { 5 | readonly MDTextFile file; 6 | 7 | public TextFile (MDTextFile file) 8 | { 9 | this.file = file; 10 | } 11 | 12 | /// 13 | /// Content of the file 14 | /// 15 | public string Text => file.Text; 16 | 17 | /// 18 | /// Full path to file 19 | /// 20 | public string Name => file.Name; 21 | 22 | /// 23 | /// Returns line and column (1-based) by given offset (0-based) 24 | /// 25 | /// 0-based 26 | /// 1-based 27 | /// 1-based 28 | public void GetLineColumnFromPosition (int offset, out int line, out int col) 29 | { 30 | file.GetLineColumnFromPosition (offset, out line, out col); 31 | } 32 | 33 | /// 34 | /// Returns offset by given line and column (1-based) 35 | /// 36 | /// line (1-based) 37 | /// column (1-based) 38 | /// offset (0-based) 39 | public int GetPositionFromLineColumn (int line, int column) 40 | { 41 | return file.GetPositionFromLineColumn (line, column); 42 | } 43 | 44 | /// 45 | /// Returns the text starting from with length= 46 | /// 47 | /// 0-based starting offset 48 | /// length of text 49 | /// 50 | public string GetText (int offset, int length) 51 | { 52 | return file.GetText (offset, length); 53 | } 54 | 55 | /// 56 | /// Returns length of the given line (1-based) 57 | /// 58 | /// 1-based line 59 | /// 60 | public int GetLineLength (int line) 61 | { 62 | return file.GetLineLength (line); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/CodeCompletionTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // CodeCompletionTests.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2017 Microsoft Corp. 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using NUnit.Framework; 28 | 29 | namespace VSCode.UnityDebug.Tests 30 | { 31 | namespace Soft 32 | { 33 | [TestFixture] 34 | public class SdbCodeCompletionTests : CodeCompletionTests 35 | { 36 | public SdbCodeCompletionTests () : base ("Mono.Debugger.Soft") 37 | { 38 | } 39 | } 40 | } 41 | 42 | namespace Win32 43 | { 44 | [TestFixture] 45 | [Platform (Include = "Win")] 46 | public class CorCodeCompletionTests : CodeCompletionTests 47 | { 48 | public CorCodeCompletionTests () : base ("MonoDevelop.Debugger.Win32") 49 | { 50 | } 51 | } 52 | } 53 | 54 | [TestFixture] 55 | public abstract class CodeCompletionTests : DebugTests 56 | { 57 | public CodeCompletionTests (string engineId) : base (engineId) 58 | { 59 | } 60 | 61 | [OneTimeSetUp] 62 | public override void SetUp () 63 | { 64 | base.SetUp (); 65 | 66 | Start ("TestEvaluation"); 67 | } 68 | 69 | [Test] 70 | public void SimpleVariablesList () 71 | { 72 | var completionData = Session.ActiveThread.Backtrace.GetFrame (0).GetExpressionCompletionData (""); 73 | Assert.Less (0, completionData.Items.Count); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "buildDev", 8 | "command": "npm", 9 | "type": "shell", 10 | "args": [ 11 | "run", 12 | "compileDev" 13 | ], 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | }, 19 | { 20 | "type": "npm", 21 | "script": "watch", 22 | "problemMatcher": "$tsc-watch", 23 | "isBackground": true, 24 | "presentation": { 25 | "reveal": "never" 26 | }, 27 | "group": { 28 | "kind": "build", 29 | "isDefault": true 30 | } 31 | }, 32 | { 33 | "type": "shell", 34 | "label": "Build UnityDebug", 35 | "command": "MSBuild.exe", 36 | "args": [ 37 | // "VSCode-UnityDebug.sln", 38 | "UnityDebug/UnityDebug.csproj", 39 | "/target:Restore,Build", 40 | "/property:Configuration=Release", 41 | // "/property:Platform=AnyCPU" 42 | ], 43 | "options": { 44 | "cwd": "./" 45 | }, 46 | "problemMatcher": [ 47 | "$msCompile" 48 | ] 49 | }, 50 | { 51 | "type": "shell", 52 | "label": "Build Debug UnityDebug", 53 | "command": "MSBuild.exe", 54 | "args": [ 55 | // "VSCode-UnityDebug.sln", 56 | "UnityDebug/UnityDebug.csproj", 57 | "/target:Restore,Build", 58 | "/property:Configuration=Debug", 59 | // "/property:Platform=AnyCPU" 60 | ], 61 | "options": { 62 | "cwd": "./" 63 | }, 64 | "problemMatcher": [ 65 | "$msCompile" 66 | ] 67 | }, 68 | { 69 | "label": "Build all", 70 | "dependsOn": [ 71 | "Build UnityDebug", 72 | "npm: compile" 73 | ], 74 | "problemMatcher": [] 75 | }, 76 | { 77 | "label": "Build all Debug", 78 | "dependsOn": [ 79 | "Build Debug UnityDebug", 80 | "npm: compile" 81 | ], 82 | "problemMatcher": [] 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /UnityDebug/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using Mono.Debugging.Client; 7 | using MonoDevelop.Debugger.Soft.Unity; 8 | using VSCodeDebug; 9 | 10 | namespace UnityDebug 11 | { 12 | public class Program 13 | { 14 | class Logger : MonoDevelop.Debugger.Soft.Unity.Log.ILogger 15 | { 16 | public void Info(string message) 17 | { 18 | Log.Write (message); 19 | } 20 | 21 | public void Warning(string message, Exception e) 22 | { 23 | Log.Write (message); 24 | } 25 | 26 | public void Error(string message, Exception e) 27 | { 28 | Log.Write (message); 29 | } 30 | 31 | } 32 | 33 | class CustomLogger : ICustomLogger 34 | { 35 | public void LogAndShowException(string message, Exception ex) 36 | { 37 | LogError(message, ex); 38 | } 39 | 40 | public void LogError(string message, Exception ex) 41 | { 42 | Log.LogError(message, ex); 43 | } 44 | 45 | public void LogMessage(string messageFormat, params object[] args) 46 | { 47 | Log.Write(string.Format(messageFormat, args)); 48 | } 49 | 50 | public string GetNewDebuggerLogFilename() 51 | { 52 | return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location) + "-another-log.txt"); 53 | } 54 | } 55 | 56 | static void Main(string[] argv) 57 | { 58 | if(argv.Length > 0 && argv[0] == "list") 59 | { 60 | Console.Write(GetUnityProcesses()); 61 | return; 62 | } 63 | 64 | // while (!Debugger.IsAttached) 65 | // { 66 | // System.Threading.Thread.Sleep(100); 67 | // } 68 | 69 | Log.Write ("UnityDebug"); 70 | 71 | MonoDevelop.Debugger.Soft.Unity.Log.AddLogger (new Logger()); 72 | 73 | try 74 | { 75 | RunSession(Console.OpenStandardInput(), Console.OpenStandardOutput()); 76 | } 77 | catch(Exception e) 78 | { 79 | Log.Write ("Exception: " + e); 80 | } 81 | } 82 | 83 | static void RunSession(Stream inputStream, Stream outputStream) 84 | { 85 | Log.Write("Running session"); 86 | DebugSession debugSession = new UnityDebugSession(); 87 | DebuggerLoggingService.CustomLogger = new CustomLogger(); 88 | debugSession.Start(inputStream, outputStream).Wait(); 89 | Log.Write("Session Terminated"); 90 | } 91 | 92 | static string GetUnityProcesses() 93 | { 94 | var processes = UnityProcessDiscovery.GetAttachableProcesses(); 95 | 96 | return string.Join("\n", processes.Select(UnityAttach.ProcessNameForPicker)); 97 | } 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /AppDomainClient/AppDomainClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E671AE70-6384-41FF-8444-6DD967F117CD} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Exe 10 | Properties 11 | AppDomainClient 12 | AppDomainClient 13 | v4.5 14 | 512 15 | 16 | 17 | AnyCPU 18 | true 19 | portable 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/ITextFile.cs: -------------------------------------------------------------------------------- 1 | // 2 | // TextFile.cs 3 | // 4 | // Author: 5 | // Artem Bukhonov 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | #pragma warning disable 1587 26 | namespace Mono.Debugging.Tests 27 | { 28 | public interface ITextFile 29 | { 30 | // TODO: Implement in another part of the class 31 | 32 | /// 33 | /// Content of the file 34 | /// 35 | string Text { get; } 36 | /// 37 | /// Full path to file 38 | /// 39 | string Name { get; } 40 | 41 | /// 42 | /// Returns line and column (1-based) by given offset (0-based) 43 | /// 44 | /// 0-based 45 | /// 1-based 46 | /// 1-based 47 | void GetLineColumnFromPosition (int offset, out int line, out int col); 48 | 49 | /// 50 | /// Returns offset by given line and column (1-based) 51 | /// 52 | /// line (1-based) 53 | /// column (1-based) 54 | /// offset (0-based) 55 | int GetPositionFromLineColumn (int line, int column); 56 | 57 | /// 58 | /// Returns the text starting from with length= 59 | /// 60 | /// 0-based starting offset 61 | /// 0-based end offset 62 | /// 63 | string GetText(int startOffset, int endOffset); 64 | 65 | /// 66 | /// Returns length of the given line (1-based) 67 | /// 68 | /// 1-based line 69 | /// 70 | int GetLineLength (int line); 71 | } 72 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Unity Debugger Extension for Visual Studio Code 2 | 3 | STATEMENT 4 | 5 | Sadly, I don't have enough time to work on this extension and most of the time I don't even have a need to debug Unity code. 6 | Even original developers and maintainers are giving up on this extension, e.g. see https://github.com/Unity-Technologies/vscode-unity-debug/issues/207#issuecomment-1131464573 7 | 8 | So I doubt there will be updates in the future. :( 9 | 10 | --- 11 | 12 | **NOTE:** This is a fork of an original Unity debugger extension and should be considered as Preview version of [Unity debugger](https://marketplace.visualstudio.com/items?itemName=Unity.unity-debug) extension. See [here](https://github.com/Unity-Technologies/vscode-unity-debug/issues/183) for the reasons of fork creation. Please refer to this [repo](https://github.com/deitry/vscode-unity-debug) for actual source code of extension. 13 | 14 | --- 15 | 16 | This extension is not officially supported by Unity Technologies. 17 | 18 | Use Visual Studio Code to debug your Unity C# projects. 19 | 20 | ## Setup 21 | 22 | - Open your Unity project folder in the Visual Studio Code. 23 | 24 | - Select the debug view on the left and click the cogwheel. 25 | 26 | ![Debug View](Screenshots/vscode-debug-view.png) 27 | 28 | - In the drop down list select “Unity Debugger”. If you do not have Unity Debugger in the list, then you already have a .vscode/Launch.json file in your project that you must delete first. 29 | 30 | ![Debugger List](Screenshots/vscode-debugger-list.png) 31 | 32 | - You will now have a .vscode/Launch.json file in your Unity project folder and can select which Unity target you wish to debug. 33 | 34 | ![Debugger List](Screenshots/vscode-debugger-unity.png) 35 | 36 | - All done. You can now debug your C# scripts in VS Code by setting a breakpoint in a C# script from your project, switching to the debug view and clicking the green triangle button to attach to Unity. Enter play mode in Unity and the breakpoint should hit in VS code. 37 | 38 | ## Attach to Process Picker 39 | 40 | New in version 1.1.0 it is now possible to select which Unity process you want to attach to from a quick pick menu. 41 | 42 | - In the command palette type "Unity Attach Debugger" 43 | 44 | - Wait a bit for the Unity processes list to appear at the top of the VS Code window. 45 | 46 | - Select the Unity process you wish to attach the debugger to. 47 | 48 | ## Usage 49 | 50 | Strings in the variable view is truncated to 100 characters, with appended ellipsis. "Example wor...". To view the entire value of this string add it to the watch fields. In addition, evaluating the variable using the debugger console will reveal the same result. 51 | 52 | ## Building 53 | 54 | To build this repository, clone it then get all submodules: 55 | 56 | ```bash 57 | git clone https://github.com/Unity-Technologies/vscode-unity-debug 58 | cd vscode-unity-debug 59 | git submodule update --init --recursive 60 | ``` 61 | Then open `VSCode-UnityDebug.sln` in Visual Studio. 62 | -------------------------------------------------------------------------------- /Tests/AppDomainClient/AppDomainClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E671AE70-6384-41FF-8444-6DD967F117CD} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Exe 10 | Properties 11 | AppDomainClient 12 | AppDomainClient 13 | v4.5 14 | 512 15 | C:\projects\mono\mono\build\builds\monodistribution\lib\mono\4.5 16 | 17 | 18 | AnyCPU 19 | true 20 | portable 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /Tests/NonUserCodeTestLib/NonUserCodeTestLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4FE265AA-4EFD-4891-B7E8-001FB76009C2} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Library 10 | Properties 11 | NonUserCodeTestLib 12 | NonUserCodeTestLib 13 | v4.5 14 | 512 15 | C:\projects\mono\mono\build\builds\monodistribution\lib\mono\4.5 16 | 17 | 18 | AnyCPU 19 | true 20 | portable 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ..\..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | -------------------------------------------------------------------------------- /UnityDebug/UnityAttach.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MonoDevelop.Debugger.Soft.Unity; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Runtime.InteropServices; 8 | using System.Text.RegularExpressions; 9 | 10 | namespace UnityDebug 11 | { 12 | public static class UnityAttach 13 | { 14 | static readonly Dictionary targetNameToProcessName = new Dictionary 15 | { 16 | { "unity editor", "Unity Editor" }, 17 | { "osx player", "OSXPlayer" }, 18 | { "windows player", "WindowsPlayer" }, 19 | { "linux player", "LinuxPlayer" }, 20 | { "ios player", "iPhonePlayer" }, 21 | { "android player", "AndroidPlayer" }, 22 | { "ps4 player", "PS4Player" }, 23 | { "xbox one player", "XboxOnePlayer" }, 24 | { "switch player", "SwitchPlayer" }, 25 | }; 26 | 27 | public static string ProcessNameForPicker(UnityProcessInfo info) 28 | { 29 | return $"{info.Name} ({info.Id}) {info.ProjectName}"; 30 | } 31 | 32 | public static IEnumerable GetAttachableProcesses(string targetName) 33 | { 34 | var match = Regex.Match(targetName, "\\(([0-9]+)\\)"); 35 | var processId = -1; 36 | if (match.Success) 37 | { 38 | processId = Convert.ToInt32(match.Groups[1].Value); 39 | targetName = targetName.Substring(0, targetName.IndexOf("(") - 1); 40 | } 41 | 42 | UnityProcessDiscovery.GetProcessOptions options = UnityProcessDiscovery.GetProcessOptions.All; 43 | 44 | if (!targetNameToProcessName.TryGetValue(targetName.ToLower(), out var processName)) 45 | { 46 | processName = targetName; 47 | } 48 | else 49 | { 50 | options = processName == "Unity Editor" 51 | ? UnityProcessDiscovery.GetProcessOptions.Editor 52 | : UnityProcessDiscovery.GetProcessOptions.Players; 53 | } 54 | 55 | Log.Write($"Trying to find all {options}"); 56 | var processes = UnityProcessDiscovery.GetAttachableProcesses(options); 57 | 58 | processes.ForEach(p => Log.Write("Found Unity process: " + p.Name + " (" + p.Id + ")")); 59 | 60 | var resProcesses = processId == -1 61 | ? processes.Where(p => p.Name.Contains(processName)).ToArray() 62 | : processes.Where(p => p.Name.Contains(processName) && p.Id == processId).ToArray(); 63 | 64 | if (resProcesses.Length == 0) 65 | { 66 | Log.Write($"Could not find the correct process name: {targetName}"); 67 | Log.Write("These are the one that could be found: "); 68 | processes = UnityProcessDiscovery.GetAttachableProcesses(); 69 | processes.ForEach(process => Log.Write($"{process.Name} : {process.Id}")); 70 | } 71 | 72 | return resProcesses; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Tests/PlayerConnectionTests/PlayerConnectionTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {13139A0F-0BD7-4771-ACE9-A567FCCD4C93} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Library 10 | Properties 11 | TestProject 12 | PlayerConnectionTests 13 | v4.7.2 14 | 512 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\..\packages\NUnit.3.11.0\lib\net45\nunit.framework.dll 38 | True 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | {d3e91d30-5b24-4743-bbe6-2ec62d7a2629} 52 | UnityDebug 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. 62 | 63 | 64 | 71 | -------------------------------------------------------------------------------- /TestApp/TestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E486F44C-C7A4-4CF1-8A17-69F0182C9E7E} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Exe 10 | Properties 11 | TestApp 12 | TestApp 13 | v4.5 14 | 512 15 | C:\projects\mono\mono\build\builds\monodistribution\lib\mono\4.5 16 | 17 | 18 | AnyCPU 19 | true 20 | portable 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\Microsoft.CSharp.dll 39 | 40 | 41 | ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 42 | 43 | 44 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.dll 45 | 46 | 47 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.Core.dll 48 | 49 | 50 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.Xml.dll 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | {e671ae70-6384-41ff-8444-6dd967f117cd} 64 | AppDomainClient 65 | 66 | 67 | 68 | 75 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/StackFrameTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // StackFrameTests.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2010 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using System; 28 | 29 | using Mono.Debugging.Soft; 30 | using Mono.Debugging.Client; 31 | 32 | using NUnit.Framework; 33 | 34 | namespace VSCode.UnityDebug.Tests 35 | { 36 | [TestFixture] 37 | public abstract class StackFrameTests: DebugTests 38 | { 39 | protected StackFrameTests (string de, bool allowTargetInvoke): base (de) 40 | { 41 | AllowTargetInvokes = allowTargetInvoke; 42 | } 43 | 44 | [OneTimeSetUp] 45 | public override void SetUp () 46 | { 47 | base.SetUp (); 48 | 49 | Start ("TestEvaluation"); 50 | } 51 | 52 | [Test] 53 | public void VirtualProperty () 54 | { 55 | var soft = Session as SoftDebuggerSession; 56 | if (soft != null && soft.ProtocolVersion < new Version (2, 31)) 57 | Assert.Ignore ("A newer version of the Mono runtime is required."); 58 | 59 | var ops = EvaluationOptions.DefaultOptions.Clone (); 60 | ops.FlattenHierarchy = false; 61 | 62 | ObjectValue val = Frame.GetExpressionValue ("c", ops); 63 | Assert.IsNotNull (val); 64 | val = val.Sync (); 65 | Assert.IsFalse (val.IsError); 66 | Assert.IsFalse (val.IsUnknown); 67 | 68 | // The C class does not have a Prop property 69 | 70 | ObjectValue prop = val.GetChildSync ("Prop", ops); 71 | Assert.IsNull (prop); 72 | 73 | prop = val.GetChildSync ("PropNoVirt1", ops); 74 | Assert.IsNull (prop); 75 | 76 | prop = val.GetChildSync ("PropNoVirt2", ops); 77 | Assert.IsNull (prop); 78 | 79 | val = val.GetChildSync ("base", ops); 80 | Assert.IsNotNull (val); 81 | val.WaitHandle.WaitOne (); 82 | Assert.IsFalse (val.IsError); 83 | Assert.IsFalse (val.IsUnknown); 84 | 85 | // The B class has a Prop property, value is 2 86 | 87 | prop = val.GetChildSync ("Prop", ops); 88 | Assert.IsNotNull (prop); 89 | Assert.AreEqual ("2", prop.Value); 90 | 91 | prop = val.GetChildSync ("PropNoVirt1", ops); 92 | Assert.IsNotNull (prop); 93 | Assert.AreEqual ("2", prop.Value); 94 | 95 | prop = val.GetChildSync ("PropNoVirt2", ops); 96 | Assert.IsNotNull (prop); 97 | Assert.AreEqual ("2", prop.Value); 98 | 99 | val = val.GetChildSync ("base", ops); 100 | Assert.IsNotNull (val); 101 | val.WaitHandle.WaitOne (); 102 | Assert.IsFalse (val.IsError); 103 | Assert.IsFalse (val.IsUnknown); 104 | 105 | // The A class has a Prop property, value is 1, but must return 2 becasue it is overriden 106 | 107 | prop = val.GetChildSync ("Prop", ops); 108 | Assert.IsNotNull (prop); 109 | Assert.AreEqual ("2", prop.Value); 110 | 111 | prop = val.GetChildSync ("PropNoVirt1", ops); 112 | Assert.IsNotNull (prop); 113 | Assert.AreEqual ("1", prop.Value); 114 | 115 | prop = val.GetChildSync ("PropNoVirt2", ops); 116 | Assert.IsNotNull (prop); 117 | Assert.AreEqual ("1", prop.Value); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Tests/PlayerConnectionTests/PlayerConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using MonoDevelop.Debugger.Soft.Unity; 3 | using NUnit.Framework; 4 | 5 | namespace PlayerConnection_spec 6 | { 7 | [TestFixture] 8 | public class ParsingPlayerConnectionString 9 | { 10 | [Test] 11 | public void XboxOneTestCase() 12 | { 13 | var dictionary = PlayerConnection.PlayerInfo.ParsePlayerString( 14 | @"[IP] 192.168.1.9 [Port] 4600 [Flags] 3 [Guid] 1343323326 [EditorId] 2183797363 [Version] 1048832 [Id] XboxOnePlayer(192.168.1.9):4601 [Debug] 1 [ProjectName] ProjectNameTest"); 15 | Assert.AreEqual("192.168.1.9", dictionary["ip"]); 16 | Assert.AreEqual("4600", dictionary["port"]); 17 | Assert.AreEqual("3", dictionary["flags"]); 18 | Assert.AreEqual("1343323326", dictionary["guid"]); 19 | Assert.AreEqual("2183797363", dictionary["editorid"]); 20 | Assert.AreEqual("1048832", dictionary["version"]); 21 | Assert.AreEqual("XboxOnePlayer(192.168.1.9):4601", dictionary["id"]); 22 | Assert.AreEqual("1", dictionary["debug"]); 23 | Assert.AreEqual("ProjectNameTest", dictionary["projectname"]); 24 | } 25 | 26 | [Test] 27 | public void PS4PlayerTestCase() 28 | { 29 | var dictionary = PlayerConnection.PlayerInfo.ParsePlayerString( 30 | @"[IP] 192.168.1.4 [Port] 35037 [Flags] 3 [Guid] 1906011430 [EditorId] 2225513615 [Version] 1048832 [Id] PS4Player(192.168.1.4):4601 [Debug] 1 [ProjectName] ProjectNameTest"); 31 | Assert.AreEqual("192.168.1.4", dictionary["ip"]); 32 | Assert.AreEqual("35037", dictionary["port"]); 33 | Assert.AreEqual("3", dictionary["flags"]); 34 | Assert.AreEqual("1906011430", dictionary["guid"]); 35 | Assert.AreEqual("2225513615", dictionary["editorid"]); 36 | Assert.AreEqual("1048832", dictionary["version"]); 37 | Assert.AreEqual("PS4Player(192.168.1.4):4601", dictionary["id"]); 38 | Assert.AreEqual("1", dictionary["debug"]); 39 | Assert.AreEqual("ProjectNameTest", dictionary["projectname"]); 40 | } 41 | } 42 | 43 | [TestFixture] 44 | public class PlayerInfo 45 | { 46 | [Test] 47 | public void XboxOneTestCase() 48 | { 49 | var playerInfo = PlayerConnection.PlayerInfo.Parse( 50 | @"[IP] 192.168.1.9 [Port] 4600 [Flags] 3 [Guid] 1343323326 [EditorId] 2183797363 [Version] 1048832 [Id] XboxOnePlayer(192.168.1.9):4601 [Debug] 1 [ProjectName] ProjectNameTest"); 51 | Assert.AreEqual("192.168.1.9", playerInfo.m_IPEndPoint.Address.ToString()); 52 | Assert.AreEqual(4600, playerInfo.m_IPEndPoint.Port); 53 | Assert.AreEqual(3, playerInfo.m_Flags); 54 | Assert.AreEqual(1343323326, playerInfo.m_Guid); 55 | Assert.AreEqual(2183797363, playerInfo.m_EditorGuid); 56 | Assert.AreEqual(1048832, playerInfo.m_Version); 57 | Assert.AreEqual("XboxOnePlayer(192.168.1.9):4601", playerInfo.m_Id); 58 | Assert.AreEqual(true, playerInfo.m_AllowDebugging); 59 | Assert.AreEqual("ProjectNameTest", playerInfo.m_ProjectName); 60 | } 61 | 62 | [Test] 63 | public void PS4PlayerTestCase() 64 | { 65 | var playerInfo = PlayerConnection.PlayerInfo.Parse( 66 | @"[IP] 192.168.1.4 [Port] 35037 [Flags] 3 [Guid] 1906011430 [EditorId] 2225513615 [Version] 1048832 [Id] PS4Player(192.168.1.4):4601 [Debug] 1 [ProjectName] ProjectNameTest"); 67 | Assert.AreEqual("192.168.1.4", playerInfo.m_IPEndPoint.Address.ToString()); 68 | Assert.AreEqual(35037, playerInfo.m_IPEndPoint.Port); 69 | Assert.AreEqual(3, playerInfo.m_Flags); 70 | Assert.AreEqual(1906011430, playerInfo.m_Guid); 71 | Assert.AreEqual(2225513615, playerInfo.m_EditorGuid); 72 | Assert.AreEqual(1048832, playerInfo.m_Version); 73 | Assert.AreEqual("PS4Player(192.168.1.4):4601", playerInfo.m_Id); 74 | Assert.AreEqual(true, playerInfo.m_AllowDebugging); 75 | Assert.AreEqual("ProjectNameTest", playerInfo.m_ProjectName); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/UnityDebug.Tests.TestApp.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {E486F44C-C7A4-4CF1-8A17-69F0182C9E7E} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Exe 10 | Properties 11 | TestApp 12 | TestApp 13 | v4.5 14 | 512 15 | C:\projects\mono\mono\build\builds\monodistribution\lib\mono\4.5 16 | 17 | 18 | AnyCPU 19 | true 20 | portable 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\Microsoft.CSharp.dll 39 | 40 | 41 | ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 42 | 43 | 44 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.dll 45 | 46 | 47 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.Core.dll 48 | 49 | 50 | ..\..\mono\mono\build\builds\monodistribution\lib\mono\4.5\System.Xml.dll 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | {e671ae70-6384-41ff-8444-6dd967f117cd} 63 | AppDomainClient 64 | 65 | 66 | {4fe265aa-4efd-4891-b7e8-001fb76009c2} 67 | NonUserCodeTestLib 68 | 69 | 70 | 71 | 78 | -------------------------------------------------------------------------------- /typescript/attach.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import {debug, workspace, commands, window, ExtensionContext, QuickPickItem, QuickPickOptions, DebugConfiguration, DebugConfigurationProvider, WorkspaceFolder, CancellationToken, ProviderResult} from 'vscode'; 4 | import {DebugProtocol} from 'vscode-debugprotocol'; 5 | import * as nls from 'vscode-nls'; 6 | import {exec} from 'child_process'; 7 | import { Exceptions, ExceptionConfigurations } from './exceptions'; 8 | 9 | const localize = nls.config({locale: process.env.VSCODE_NLS_CONFIG})(); 10 | var exceptions; 11 | 12 | const DEFAULT_EXCEPTIONS: ExceptionConfigurations = { 13 | "System.Exception": "never", 14 | "System.SystemException": "never", 15 | "System.ArithmeticException": "never", 16 | "System.ArrayTypeMismatchException": "never", 17 | "System.DivideByZeroException": "never", 18 | "System.IndexOutOfRangeException": "never", 19 | "System.InvalidCastException": "never", 20 | "System.NullReferenceException": "never", 21 | "System.OutOfMemoryException": "never", 22 | "System.OverflowException": "never", 23 | "System.StackOverflowException": "never", 24 | "System.TypeInitializationException": "never" 25 | }; 26 | 27 | export function activate(context: ExtensionContext) { 28 | context.subscriptions.push(debug.registerDebugConfigurationProvider("unity", new UnityDebugConfigurationProvider())); 29 | 30 | exceptions = new Exceptions(DEFAULT_EXCEPTIONS); 31 | window.registerTreeDataProvider("exceptions", exceptions); 32 | context.subscriptions.push(commands.registerCommand('exceptions.always', exception => exceptions.always(exception))); 33 | context.subscriptions.push(commands.registerCommand('exceptions.never', exception => exceptions.never(exception))); 34 | context.subscriptions.push(commands.registerCommand('exceptions.addEntry', t => exceptions.addEntry(t))); 35 | context.subscriptions.push(commands.registerCommand('attach.attachToDebugger', config => startSession(context, config))); 36 | } 37 | 38 | export function deactivate() { 39 | } 40 | 41 | class UnityDebugConfigurationProvider implements DebugConfigurationProvider { 42 | provideDebugConfigurations(folder: WorkspaceFolder | undefined, token?: CancellationToken): ProviderResult { 43 | 44 | const config = [ 45 | { 46 | name: "Unity Editor", 47 | type: "unity", 48 | path: folder.uri.path + "/Library/EditorInstance.json", 49 | request: "launch" 50 | }, 51 | { 52 | name: "Windows Player", 53 | type: "unity", 54 | request: "launch" 55 | }, 56 | { 57 | name: "OSX Player", 58 | type: "unity", 59 | request: "launch" 60 | }, 61 | { 62 | name: "Linux Player", 63 | type: "unity", 64 | request: "launch" 65 | }, 66 | { 67 | name: "iOS Player", 68 | type: "unity", 69 | request: "launch" 70 | }, 71 | { 72 | name: "Android Player", 73 | type: "unity", 74 | request: "launch" 75 | }, 76 | { 77 | name: "Xbox One Player", 78 | type: "unity", 79 | request: "launch" 80 | }, 81 | { 82 | name: "PS4 Player", 83 | type: "unity", 84 | request: "launch" 85 | }, 86 | { 87 | name: "SwitchPlayer", 88 | type: "unity", 89 | request: "launch" 90 | } 91 | ]; 92 | return config; 93 | } 94 | 95 | resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfiguration: DebugConfiguration, token?: CancellationToken): ProviderResult { 96 | if (!debugConfiguration.type) { 97 | // If the config doesn't look functional force VSCode to open a configuration file https://github.com/Microsoft/vscode/issues/54213 98 | return null; 99 | } 100 | 101 | if (debugConfiguration && !debugConfiguration.__exceptionOptions) { 102 | debugConfiguration.__exceptionOptions = exceptions.convertToExceptionOptionsDefault(); 103 | } 104 | return debugConfiguration; 105 | } 106 | } 107 | 108 | function startSession(context: ExtensionContext, config: any) { 109 | let execCommand = ""; 110 | if (process.platform !== 'win32') 111 | execCommand = "mono "; 112 | 113 | exec(execCommand + context.extensionPath + "/bin/UnityDebug.exe list", async function (error, stdout, stderr) { 114 | const processes = []; 115 | const lines = stdout.split("\n"); 116 | for (let i = 0; i < lines.length; i++) { 117 | if (lines[i]) { 118 | processes.push(lines[i]); 119 | } 120 | } 121 | 122 | if (processes.length == 0) { 123 | window.showErrorMessage("No Unity Process Found."); 124 | } else { 125 | var chosen = await window.showQuickPick(processes); 126 | if (!chosen) { 127 | return; 128 | } 129 | const config = { 130 | "name": chosen, 131 | "request": "launch", 132 | "type": "unity", 133 | "__exceptionOptions": exceptions.convertToExceptionOptionsDefault() 134 | } 135 | let response = await debug.startDebugging(undefined, config); 136 | 137 | console.log("debug ended: " + response); 138 | } 139 | }); 140 | } -------------------------------------------------------------------------------- /typescript/exceptions.ts: -------------------------------------------------------------------------------- 1 | import {QuickPickItem, TreeDataProvider, Event, EventEmitter, TreeItem, ProviderResult, window, InputBoxOptions} from 'vscode'; 2 | import * as vscode from 'vscode'; 3 | import * as nls from 'vscode-nls'; 4 | import {DebugProtocol} from 'vscode-debugprotocol'; 5 | 6 | 7 | //----- configureExceptions --------------------------------------------------------------------------------------------------- 8 | // we store the exception configuration in the workspace or user settings as 9 | export type ExceptionConfigurations = { [exception: string]: DebugProtocol.ExceptionBreakMode; }; 10 | 11 | class ExceptionItem implements QuickPickItem { 12 | label: string; 13 | description: string; 14 | model: DebugProtocol.ExceptionOptions 15 | } 16 | 17 | enum ExceptionMode { 18 | Always, 19 | Never, 20 | Unhandled 21 | } 22 | 23 | export class Exceptions implements TreeDataProvider { 24 | private _onDidChangeTreeData: EventEmitter = new EventEmitter(); 25 | readonly onDidChangeTreeData?: Event = this._onDidChangeTreeData.event; 26 | 27 | constructor(private exceptions: ExceptionConfigurations) { 28 | } 29 | 30 | public always(element: ExceptionBreakpoints) { 31 | this.exceptions[element.name] = "always"; 32 | element.setMode(ExceptionMode.Always); 33 | this._onDidChangeTreeData.fire(element); 34 | this.setExceptionBreakpoints(this.exceptions); 35 | } 36 | 37 | public never(element: ExceptionBreakpoints) { 38 | this.exceptions[element.name] = "never"; 39 | element.setMode(ExceptionMode.Never); 40 | this._onDidChangeTreeData.fire(element); 41 | this.setExceptionBreakpoints(this.exceptions); 42 | } 43 | 44 | public unhandled(element: ExceptionBreakpoints) { 45 | this.exceptions[element.name] = "unhandled"; 46 | element.setMode(ExceptionMode.Unhandled); 47 | this._onDidChangeTreeData.fire(element); 48 | this.setExceptionBreakpoints(this.exceptions); 49 | } 50 | 51 | public addEntry(t: any) { 52 | let options: InputBoxOptions = { 53 | placeHolder: "(Namespace.ExceptionName)" 54 | } 55 | 56 | window.showInputBox(options).then(value => { 57 | if (!value) { 58 | return; 59 | } 60 | this.exceptions[value] = "never"; 61 | this._onDidChangeTreeData.fire(null); 62 | }); 63 | } 64 | 65 | setExceptionBreakpoints(exceptionConfigs: ExceptionConfigurations) { 66 | 67 | const args: DebugProtocol.SetExceptionBreakpointsArguments = { 68 | filters: [], 69 | exceptionOptions: this.exceptionConfigurationToExceptionOptions(exceptionConfigs) 70 | }; 71 | 72 | vscode.debug.activeDebugSession.customRequest('setExceptionBreakpoints', args).then(); 73 | } 74 | 75 | public convertToExceptionOptionsDefault(): DebugProtocol.ExceptionOptions[] { 76 | return this.exceptionConfigurationToExceptionOptions(this.exceptions); 77 | } 78 | 79 | public exceptionConfigurationToExceptionOptions(exceptionConfigs: ExceptionConfigurations): DebugProtocol.ExceptionOptions[] { 80 | const exceptionItems: DebugProtocol.ExceptionOptions[] = []; 81 | for (const exception in exceptionConfigs) { 82 | exceptionItems.push({ 83 | path: [{names: [exception]}], 84 | breakMode: exceptionConfigs[exception] 85 | }); 86 | } 87 | return exceptionItems; 88 | } 89 | 90 | public exceptionConfigurationToExceptionMode(exceptionConfig: string): ExceptionMode { 91 | switch (exceptionConfig) 92 | { 93 | case "always": return ExceptionMode.Always; 94 | case "never": return ExceptionMode.Never; 95 | case "unhandled": return ExceptionMode.Unhandled; 96 | default: throw new Error(exceptionConfig + ": is not a known exceptionConfig"); 97 | } 98 | } 99 | 100 | getTreeItem(element: ExceptionBreakpoints): TreeItem | Thenable { 101 | return element; 102 | } 103 | 104 | getChildren(element?: ExceptionBreakpoints): ProviderResult { 105 | if (!this.exceptions) { 106 | window.showInformationMessage('No exception found'); 107 | return Promise.resolve([]); 108 | } 109 | 110 | return new Promise(resolve => { 111 | if (element) { 112 | const exceptionItems: ExceptionBreakpoints[] = []; 113 | for (const exception in this.exceptions) { 114 | exceptionItems.push(new ExceptionBreakpoints(exception, this.exceptionConfigurationToExceptionMode(this.exceptions[exception]))); 115 | } 116 | resolve(exceptionItems); 117 | } else { 118 | const exceptionItems: ExceptionBreakpoints[] = []; 119 | for (const exception in this.exceptions) { 120 | exceptionItems.push(new ExceptionBreakpoints(exception, this.exceptionConfigurationToExceptionMode(this.exceptions[exception]))); 121 | } 122 | resolve(exceptionItems); 123 | } 124 | }); 125 | } 126 | getParent?(element: ExceptionBreakpoints): ProviderResult { 127 | return null; 128 | } 129 | } 130 | 131 | class ExceptionBreakpoints extends TreeItem { 132 | constructor( 133 | public name: string, 134 | public mode: ExceptionMode, 135 | ) { 136 | super(mode + " : " + name); 137 | this.setMode(mode); 138 | } 139 | 140 | setMode(mode: ExceptionMode) { 141 | this.mode = mode; 142 | this.label = this.tooltip = `[${this.mode == ExceptionMode.Always ? "✔" : "✖"}] ${this.name}`; 143 | } 144 | 145 | contextValue = 'exception'; 146 | } -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/UnityDebug.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Debug 7 | AnyCPU 8 | {33071BC3-C0E6-47F1-96CE-50BBCE820DD4} 9 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10 | Library 11 | Properties 12 | UnityDebug.Tests 13 | UnityDebug.Tests 14 | v4.7.2 15 | 512 16 | true 17 | 18 | 19 | AnyCPU 20 | true 21 | full 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | prompt 26 | 4 27 | 28 | 29 | AnyCPU 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | ..\..\packages\NUnit.3.12.0\lib\net45\nunit.framework.dll 40 | True 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | {372e8e3e-29d5-4b4d-88a2-4711cd628c4e} 70 | Mono.Debugger.Soft 71 | 72 | 73 | {e671ae70-6384-41ff-8444-6dd967f117cd} 74 | AppDomainClient 75 | 76 | 77 | {de40756e-57f6-4af2-b155-55e3a88cced8} 78 | Mono.Debugging.Soft 79 | 80 | 81 | {90c99adb-7d4b-4eb4-98c2-40bd1b14c7d2} 82 | Mono.Debugging 83 | 84 | 85 | {e486f44c-c7a4-4cf1-8a17-69f0182c9e7e} 86 | UnityDebug.Tests.TestApp 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. 96 | 97 | 98 | 99 | 106 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | UnityDebug - Unity Debugger Extension for Visual Studio Code 2 | -------------------------------------------------------------------------------- 3 | 4 | Git: https://github.com/Unity-Technologies/vscode-unity-debug 5 | 6 | Changes 7 | ------- 8 | 9 | 3.0.11 10 | ===== 11 | - Attempt to fix error during processing `stackTrace` (https://github.com/Unity-Technologies/vscode-unity-debug/issues/183) 12 | 13 | 3.0.10 14 | ===== 15 | - Fix launch.json creation when there is no configuration (https://github.com/Unity-Technologies/vscode-unity-debug/issues/194) 16 | 17 | 3.0.9 18 | ===== 19 | - Fix extension entry point after moving to webpack 20 | 21 | 3.0.8 22 | ===== 23 | - Use webpack to bundle extension 24 | 25 | 3.0.7 26 | ===== 27 | - Fix Changelog not appearing in the extension 28 | 29 | 3.0.6 30 | ===== 31 | - Attempt to fix "Could not find target name ..." for specific cases (https://github.com/Unity-Technologies/vscode-unity-debug/issues/193) 32 | 33 | 3.0.5 34 | ===== 35 | - Attempt to fix path issue on Linux (https://github.com/Unity-Technologies/vscode-unity-debug/issues/195) 36 | 37 | 3.0.4 38 | ===== 39 | - Minor changes in exception handling to track down https://github.com/Unity-Technologies/vscode-unity-debug/issues/183 40 | - More graceful debugger stop by supporting `terminate` request 41 | 42 | 3.0.3 43 | ===== 44 | - Activate extension only on specific events 45 | 46 | 3.0.2 47 | ===== 48 | - Update vscode dependencies 49 | 50 | 3.0.1 51 | ===== 52 | - Improve stability with latest VS Code 53 | 54 | 3.0.0 55 | ===== 56 | - Update debugger libraries. Fixes added Roslyn to evaluate certain expressions sent to the debugger. 57 | 58 | 2.7.0 59 | ===== 60 | - Update debugger libs. This patch includes sending the absolute file path to the debugger agent on native. 61 | 62 | 2.6.7 63 | ===== 64 | - Fix launch settings configuration through resolve. 65 | 66 | 2.6.6 67 | ===== 68 | - Fix duplicate line removing breakpoints. 69 | 70 | 2.6.5 71 | ===== 72 | - Initialize commands on vs code start up time. 73 | 74 | 2.6.4 75 | ===== 76 | - Improve attaching to unity processes. Added support for PS4, Xbox One, and Switch. 77 | 78 | 2.6.3 79 | ===== 80 | - Fix regression within attach unity debugger. This is necessary when EditorInstance.json does not exist. 81 | 82 | 2.6.2 83 | ===== 84 | - Missing EditorInstance.json file will no longer crash the program, instead it will terminated and report steps the user should take. 85 | 86 | 2.6.1 87 | ===== 88 | - Updated debugger-libs to stop hovering from stack overflowing, due to miss use of NRefactory. 89 | 90 | 2.6.0 91 | ===== 92 | - Multithreaded stack trace unwrapping is now enabled. Making it possible to switch context. 93 | 94 | 2.5.0 95 | ===== 96 | - New support for halt on exception. In debug view a list of exceptions control which to break on. 97 | 98 | 2.4.2 99 | ===== 100 | - Added support for Library/EditorInstance.json. The correct process is attached and multiple editors are running. 101 | 102 | 2.4.1 103 | ===== 104 | - Fix modification exception when setting breakpoints. 105 | 106 | 2.4.0 107 | ===== 108 | - Added support for attaching individual unity processes by use of commands. 109 | 110 | 2.3.0 111 | ===== 112 | - Added support for conditional breakpoints. 113 | 114 | 2.2.0 115 | ===== 116 | - Added support for setValue. This makes it possible to modify variables at runtime. 117 | 118 | 2.1.0 119 | ===== 120 | - Added support for circumventing string truncation by disabling ellipsing on strings in watch field. 121 | 122 | 2.0.1 123 | ===== 124 | - Fix duplicate key exception when assigning breakpoints. 125 | 126 | 2.0.0 127 | ===== 128 | - Updated packages to support .NET 4.6 runtime in Unity. 129 | - Fix issue with being able to detach from Unity, which would cause the Unity Editor to hang. 130 | - Various instabilities fixes, such as LINQ debugging for .NET 4.6 runtime, hovering variables, complex class debugging etc. 131 | 132 | 1.3.0 133 | ===== 134 | - Fix "Error: command 'vscode.startDebug' not found" error when using "Unity Attach Debugger" command. 135 | - Fix issue with being unable to attach to Unity Editor because of "UnityCrashHandler64" and "Unity Hub" processes. 136 | 137 | 1.2.1 138 | ===== 139 | - Fix issue with "Unity Attach Debugger" not working due to missing attach.js file. 140 | 141 | 1.2.0 142 | ===== 143 | - Add support for hovering on variables. Patch contributed by JohnPoison. 144 | - Update debugger client library to latest version. Fixes debugging issues in Unity 5.5 and above. 145 | - Fix issue with not being able to attach if unityiproxy (Unity Remote) process is running. 146 | - Added MIT LICENSE.txt 147 | 148 | 1.1.0 149 | ===== 150 | - Added "Unity Attach Debugger" to command palette. Patch contributed by Dominick. 151 | - Fixed issue with being unable to attach to Linux Player. 152 | 153 | 1.0.4 154 | ===== 155 | 156 | - Fixed issue with case sensitive path compare. 157 | (https://github.com/Unity-Technologies/vscode-unity-debug/issues/14) 158 | 159 | 1.0.3 160 | ===== 161 | 162 | - Improved logging when multiple Unity processes are found. 163 | 164 | 1.0.2 165 | ===== 166 | 167 | - Improved support for expressions added with "Add Watch" 168 | 169 | - Fixed issue with being unable to attach to Unity editor on Ubuntu, when 170 | using Unity graphical shell. 171 | 172 | - Attaching to the Unity Editor is faster. 173 | 174 | - Update debugger protocol to latest version. 175 | 176 | 1.0.1 177 | ===== 178 | 179 | - Fixed issue with using "Add Watch" not generating valid expressions. 180 | 181 | 1.0.0 182 | ===== 183 | 184 | - Fixed issue with being unable to add a watch. 185 | 186 | 0.5.0 187 | ===== 188 | 189 | - Added support for attaching to Windows, OSX, Linux, Android and iOS players 190 | 191 | - Added log file 192 | OSX/Linux: ${HOME}/.vscode/extensions/Unity.unity-debug-x.y.z/bin/UnityDebug-log.txt 193 | Windows: %USERPROFILE%\.vscode\extensions\Unity.unity-debug-x.y.z\bin\UnityDebug-log.txt 194 | 195 | - Fix issue with "unity" being marked as unknown "type" in launch.json 196 | 197 | 0.1.0 198 | ===== 199 | 200 | - Initial release. 201 | 202 | - Only attaching to Unity editor is supported. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unity-debug", 3 | "displayName": "Debugger for Unity", 4 | "version": "3.0.11", 5 | "publisher": "deitry", 6 | "description": "Unity debugger extension (Preview)", 7 | "license": "MIT", 8 | "engines": { 9 | "vscode": "^1.47.x" 10 | }, 11 | "preview": true, 12 | "extensionDependencies": [ 13 | "ms-dotnettools.csharp" 14 | ], 15 | "devDependencies": { 16 | "@types/vscode": "^1.47.0", 17 | "ts-loader": "5.3.3", 18 | "vscode-debugprotocol": "^1.42.0", 19 | "webpack": "^5.24.3", 20 | "webpack-cli": "^4.5.0" 21 | }, 22 | "dependencies": { 23 | "@types/node": "^14.14.7", 24 | "make": "^0.0.0", 25 | "npm": "^7.0.10", 26 | "vscode-nls": "^5.0.0" 27 | }, 28 | "categories": [ 29 | "Debuggers" 30 | ], 31 | "keywords": [ 32 | "unity", 33 | "unity3d", 34 | "csharp", 35 | "debugger", 36 | "debug" 37 | ], 38 | "homepage": "https://github.com/Unity-Technologies/vscode-unity-debug", 39 | "bugs": { 40 | "url": "https://github.com/Unity-Technologies/vscode-unity-debug/issues" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/deitry/vscode-unity-debug.git" 45 | }, 46 | "icon": "Images/dark/Unity.png", 47 | "main": "./dist/extension", 48 | "scripts": { 49 | "vscode:prepublish": "make build && webpack --mode production", 50 | "webpack-dev": "webpack --mode development --watch", 51 | "webpack": "webpack --mode development", 52 | "prepare": "make build", 53 | "compile": "make build", 54 | "compileDev": "make build && tsc -p ./typescript && webpack --mode development", 55 | "watch": "tsc -w -p ./src/typescript" 56 | }, 57 | "activationEvents": [ 58 | "onCommand:attach.attachToDebugger", 59 | "onCommand:exceptions.addEntry", 60 | "onCommand:exceptions.always", 61 | "onCommand:exceptions.never", 62 | "onView:exceptions", 63 | "onDebug" 64 | ], 65 | "contributes": { 66 | "breakpoints": [ 67 | { 68 | "language": "csharp" 69 | } 70 | ], 71 | "commands": [ 72 | { 73 | "command": "attach.attachToDebugger", 74 | "title": "Unity Attach Debugger" 75 | }, 76 | { 77 | "command": "exceptions.addEntry", 78 | "title": "Add", 79 | "icon": { 80 | "dark": "Images/dark/stage.svg", 81 | "light": "Images/light/stage.svg" 82 | } 83 | }, 84 | { 85 | "command": "exceptions.always", 86 | "title": "Always" 87 | }, 88 | { 89 | "command": "exceptions.never", 90 | "title": "Never" 91 | } 92 | ], 93 | "views": { 94 | "debug": [ 95 | { 96 | "id": "exceptions", 97 | "name": "Exception Breakpoints" 98 | } 99 | ] 100 | }, 101 | "menus": { 102 | "view/title": [ 103 | { 104 | "command": "exceptions.addEntry", 105 | "when": "view == exceptions", 106 | "group": "navigation" 107 | } 108 | ], 109 | "view/item/context": [ 110 | { 111 | "command": "exceptions.always", 112 | "when": "view == exceptions && viewItem == exception" 113 | }, 114 | { 115 | "command": "exceptions.never", 116 | "when": "view == exceptions && viewItem == exception" 117 | } 118 | ] 119 | }, 120 | "debuggers": [ 121 | { 122 | "type": "unity", 123 | "label": "Unity Debugger", 124 | "program": "./bin/UnityDebug.exe", 125 | "osx": { 126 | "runtime": "mono" 127 | }, 128 | "linux": { 129 | "runtime": "mono" 130 | }, 131 | "configurationAttributes": { 132 | "launch": { 133 | "properties": { 134 | "path": { 135 | "type": "string", 136 | "description": "Used for attaching to Unity Editor when multiple instances are running" 137 | } 138 | } 139 | } 140 | }, 141 | "configurationSnippets": [ 142 | { 143 | "label": "Unity Debug: Unity Editor", 144 | "body": { 145 | "name": "Unity Editor", 146 | "type": "unity", 147 | "path": "^\"\\${workspaceFolder}/Library/EditorInstance.json\"", 148 | "request": "launch" 149 | } 150 | }, 151 | { 152 | "label": "Unity Debug: Windows Player", 153 | "body": { 154 | "name": "Windows Player", 155 | "type": "unity", 156 | "request": "launch" 157 | } 158 | }, 159 | { 160 | "label": "Unity Debug: OSX Player", 161 | "body": { 162 | "name": "OSX Player", 163 | "type": "unity", 164 | "request": "launch" 165 | } 166 | }, 167 | { 168 | "label": "Unity Debug: Linux Player", 169 | "body": { 170 | "name": "Linux Player", 171 | "type": "unity", 172 | "request": "launch" 173 | } 174 | }, 175 | { 176 | "label": "Unity Debug: iOS Player", 177 | "body": { 178 | "name": "iOS Player", 179 | "type": "unity", 180 | "request": "launch" 181 | } 182 | }, 183 | { 184 | "label": "Unity Debug: Android Player", 185 | "body": { 186 | "name": "Android Player", 187 | "type": "unity", 188 | "request": "launch" 189 | } 190 | }, 191 | { 192 | "label": "Unity Debug: Xbox One Player", 193 | "body": { 194 | "name": "Xbox One Player", 195 | "type": "unity", 196 | "request": "launch" 197 | } 198 | }, 199 | { 200 | "label": "Unity Debug: PS4 Player", 201 | "body": { 202 | "name": "PS4 Player", 203 | "type": "unity", 204 | "request": "launch" 205 | } 206 | }, 207 | { 208 | "label": "Unity Debug: SwitchPlayer", 209 | "body": { 210 | "name": "SwitchPlayer", 211 | "type": "unity", 212 | "request": "launch" 213 | } 214 | } 215 | ] 216 | } 217 | ] 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /TestApp/AdvancedEvaluation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // AdvancedEvaluation.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using System.Threading.Tasks; 28 | using System.Collections; 29 | using System.Collections.Generic; 30 | using System.Linq; 31 | 32 | namespace UnityDebug.TestApp 33 | { 34 | public class AdvancedEvaluation 35 | { 36 | public static void RunTest () 37 | { 38 | var obj = new AdvancedEvaluation (); 39 | obj.Test (); 40 | } 41 | 42 | public static string NextMethodToCall = ""; 43 | 44 | public void Test () 45 | { 46 | while (true) { 47 | Console.Write ("");/*break*/ 48 | try { 49 | typeof(AdvancedEvaluation).GetMethod (NextMethodToCall).Invoke (this, null); 50 | } catch { 51 | } 52 | } 53 | } 54 | 55 | public static void LocalFunctionVariablesTest() 56 | { 57 | var a = 23; 58 | localFunction(24, "hi"); 59 | 60 | int localFunction(int b, string c) 61 | { 62 | var d = 25; 63 | return a + b + d;/*07a0e6ef-e1d2-4f11-ab67-78e6ae5ea3bb*/ 64 | } 65 | } 66 | 67 | public static void LocalFunctionNoCaptureVariablesTest() 68 | { 69 | localFunction(17, 23, 31); 70 | 71 | int localFunction(int a, int b, int c) 72 | { 73 | return a + b + c;/*056bb4b5-1c7a-4e21-bd93-abd7389809d0*/ 74 | } 75 | } 76 | 77 | public static void LocalFunctionCaptureDelegateVariablesTest() 78 | { 79 | var add = LocalFunctionCaptureDelegateVariablesTest_CreateAdder(7); 80 | add(5); 81 | } 82 | 83 | static Func LocalFunctionCaptureDelegateVariablesTest_CreateAdder(int i) 84 | { 85 | return localFunction; 86 | 87 | int localFunction(int a) 88 | { 89 | return a + i;/*94100486-d7c4-4239-9d87-ad61287117d5*/ 90 | } 91 | } 92 | 93 | public void YieldMethodTest () 94 | { 95 | YieldMethod ().ToList (); 96 | } 97 | 98 | public IEnumerable YieldMethod () 99 | { 100 | var someVariable = new ArrayList (); 101 | yield return "1";/*0b1212f8-9035-43dc-bf01-73efd078d680*/ 102 | someField = "das1"; 103 | someVariable.Add (1); 104 | yield return "2";/*e96b28bb-59bf-445d-b71f-316726ba4c52*/ 105 | someField = "das2"; 106 | someVariable.Add (2); 107 | yield return "3";/*760feb92-176a-43d7-b5c9-116c4a3c6a6c*/ 108 | yield return "4";/*a9a9aa9d-6b8b-4724-9741-2a3e1fb435e8*/ 109 | } 110 | 111 | public void Bug33193Test () 112 | { 113 | Bug33193 ().Wait (); 114 | } 115 | 116 | public async Task Bug33193() 117 | { 118 | var list = new [] { "a", "b", "c" }; 119 | foreach (var item1 in list) { 120 | item1.ToString (); 121 | } 122 | await Task.Delay (0); 123 | foreach (var item1 in list) { 124 | item1.ToString ();/*f1665382-7ddc-4c65-9c20-39d4a0ae9cf1*/ 125 | } 126 | } 127 | 128 | public class Tuples 129 | { 130 | public List<(string xmlNs, object clrNs)> Usings { get; set; } = new List<(string xmlNs, object clrNs)> () { ("test", null) }; 131 | } 132 | 133 | public void NamedTupleIndexMissmatchTest () 134 | { 135 | foreach (var item in new Tuples ().Usings) { 136 | item.xmlNs.ToUpper ();/*9196deef-9d41-41d6-bcef-9e3ef58f9635*/ 137 | } 138 | } 139 | 140 | public void Bug24998Test () 141 | { 142 | Bug24998 ().Wait (); 143 | } 144 | 145 | string someField; 146 | public async Task Bug24998 () 147 | { 148 | someField = "das"; 149 | var someVariable = new ArrayList (); 150 | var action = new Action (() => someVariable.Add (1)); 151 | await Task.Delay (100); 152 | action (); 153 | someVariable.Add (someField);/*cc622137-a162-4b91-a85c-88241e68c3ea*/ 154 | } 155 | 156 | 157 | public void InvocationsCountDuringExpandingTest () 158 | { 159 | var mutableFieldClass = new MutableFieldClass (); 160 | Console.WriteLine("InvocationsCountDuringExpandingTest breakpoint");/*8865cace-6b57-42cc-ad55-68a2c12dd3d7*/ 161 | } 162 | 163 | class MutableFieldClass 164 | { 165 | int sharedX = 0; 166 | 167 | public MutableField Prop1 168 | { 169 | get { return new MutableField(sharedX++); } 170 | } 171 | 172 | public MutableField Prop2 173 | { 174 | get { return new MutableField(sharedX++); } 175 | } 176 | } 177 | 178 | 179 | class MutableField 180 | { 181 | int x; 182 | 183 | public MutableField(int x) 184 | { 185 | this.x = x; 186 | } 187 | } 188 | 189 | public void MethodWithTypeGenericArgsEval () 190 | { 191 | var a = new A("Just A"); 192 | var wrappedA = new Wrapper(new A("wrappedA")); 193 | var genericClass = new GenericClass(new A("Constructor arg A")); 194 | //genericClass.BaseMethodWithClassTArg (wrappedA); 195 | //genericClass.RetMethodWithClassTArg (a) 196 | Console.WriteLine("Break for MethodWithTypeGenericArgsEval");/*ba6350e5-7149-4cc2-a4cf-8a54c635eb38*/ 197 | } 198 | 199 | class A 200 | { 201 | public A(string myProp) 202 | { 203 | MyProp = myProp; 204 | } 205 | 206 | public string MyProp { get; set; } 207 | 208 | public override string ToString() 209 | { 210 | return MyProp; 211 | } 212 | } 213 | 214 | class GenericBaseClass 215 | { 216 | public readonly TBaseClassArg myArg; 217 | 218 | public GenericBaseClass(TBaseClassArg arg) 219 | { 220 | myArg = arg; 221 | } 222 | 223 | public TBaseClassArg BaseMethodWithClassTArg(TBaseClassArg arg) 224 | { 225 | return arg; 226 | } 227 | 228 | 229 | } 230 | 231 | class Wrapper 232 | { 233 | public TObj obj; 234 | 235 | public Wrapper(TObj obj) 236 | { 237 | this.obj = obj; 238 | } 239 | 240 | public override string ToString() 241 | { 242 | return string.Format("Wrapper({0})", obj); 243 | } 244 | } 245 | 246 | class GenericClass : GenericBaseClass> 247 | { 248 | public GenericClass(TOfClass arg) : base(new Wrapper(arg)) 249 | { 250 | } 251 | 252 | public void VoidMethodWithClassTArg(TOfClass tOfClass) {} 253 | public TOfClass RetMethodWithClassTArg(TOfClass tOfClass) {return tOfClass;} 254 | 255 | public void VoidMethodWithMethodTArg(TOfMethod tOfMethod) { } 256 | public void VoidMethodWithMethodAndClassTArg(TOfMethod tOfMethod, TOfClass tOfClass) { } 257 | 258 | } 259 | } 260 | } 261 | 262 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests.TestApp/AdvancedEvaluation.cs: -------------------------------------------------------------------------------- 1 | // 2 | // AdvancedEvaluation.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using System.Threading.Tasks; 28 | using System.Collections; 29 | using System.Collections.Generic; 30 | using System.Linq; 31 | 32 | namespace UnityDebug.Tests.TestApp 33 | { 34 | public class AdvancedEvaluation 35 | { 36 | public static void RunTest () 37 | { 38 | var obj = new AdvancedEvaluation (); 39 | obj.Test (); 40 | } 41 | 42 | public static string NextMethodToCall = ""; 43 | 44 | public void Test () 45 | { 46 | while (true) { 47 | Console.Write ("");/*break*/ 48 | try { 49 | typeof(AdvancedEvaluation).GetMethod (NextMethodToCall).Invoke (this, null); 50 | } catch { 51 | } 52 | } 53 | } 54 | 55 | public static void LocalFunctionVariablesTest() 56 | { 57 | var a = 23; 58 | localFunction(24, "hi"); 59 | 60 | int localFunction(int b, string c) 61 | { 62 | var d = 25; 63 | return a + b + d;/*07a0e6ef-e1d2-4f11-ab67-78e6ae5ea3bb*/ 64 | } 65 | } 66 | 67 | public static void LocalFunctionNoCaptureVariablesTest() 68 | { 69 | localFunction(17, 23, 31); 70 | 71 | int localFunction(int a, int b, int c) 72 | { 73 | return a + b + c;/*056bb4b5-1c7a-4e21-bd93-abd7389809d0*/ 74 | } 75 | } 76 | 77 | public static void LocalFunctionCaptureDelegateVariablesTest() 78 | { 79 | var add = LocalFunctionCaptureDelegateVariablesTest_CreateAdder(7); 80 | add(5); 81 | } 82 | 83 | static Func LocalFunctionCaptureDelegateVariablesTest_CreateAdder(int i) 84 | { 85 | return localFunction; 86 | 87 | int localFunction(int a) 88 | { 89 | return a + i;/*94100486-d7c4-4239-9d87-ad61287117d5*/ 90 | } 91 | } 92 | 93 | public void YieldMethodTest () 94 | { 95 | YieldMethod ().ToList (); 96 | } 97 | 98 | public IEnumerable YieldMethod () 99 | { 100 | var someVariable = new ArrayList (); 101 | yield return "1";/*0b1212f8-9035-43dc-bf01-73efd078d680*/ 102 | someField = "das1"; 103 | someVariable.Add (1); 104 | yield return "2";/*e96b28bb-59bf-445d-b71f-316726ba4c52*/ 105 | someField = "das2"; 106 | someVariable.Add (2); 107 | yield return "3";/*760feb92-176a-43d7-b5c9-116c4a3c6a6c*/ 108 | yield return "4";/*a9a9aa9d-6b8b-4724-9741-2a3e1fb435e8*/ 109 | } 110 | 111 | public void Bug33193Test () 112 | { 113 | Bug33193 ().Wait (); 114 | } 115 | 116 | public async Task Bug33193() 117 | { 118 | var list = new [] { "a", "b", "c" }; 119 | foreach (var item1 in list) { 120 | item1.ToString (); 121 | } 122 | await Task.Delay (0); 123 | foreach (var item1 in list) { 124 | item1.ToString ();/*f1665382-7ddc-4c65-9c20-39d4a0ae9cf1*/ 125 | } 126 | } 127 | 128 | public class Tuples 129 | { 130 | public List<(string xmlNs, object clrNs)> Usings { get; set; } = new List<(string xmlNs, object clrNs)> () { ("test", null) }; 131 | } 132 | 133 | public void NamedTupleIndexMissmatchTest () 134 | { 135 | foreach (var item in new Tuples ().Usings) { 136 | item.xmlNs.ToUpper ();/*9196deef-9d41-41d6-bcef-9e3ef58f9635*/ 137 | } 138 | } 139 | 140 | public void Bug24998Test () 141 | { 142 | Bug24998 ().Wait (); 143 | } 144 | 145 | string someField; 146 | public async Task Bug24998 () 147 | { 148 | someField = "das"; 149 | var someVariable = new ArrayList (); 150 | var action = new Action (() => someVariable.Add (1)); 151 | await Task.Delay (100); 152 | action (); 153 | someVariable.Add (someField);/*cc622137-a162-4b91-a85c-88241e68c3ea*/ 154 | } 155 | 156 | 157 | public void InvocationsCountDuringExpandingTest () 158 | { 159 | var mutableFieldClass = new MutableFieldClass (); 160 | Console.WriteLine("InvocationsCountDuringExpandingTest breakpoint");/*8865cace-6b57-42cc-ad55-68a2c12dd3d7*/ 161 | } 162 | 163 | class MutableFieldClass 164 | { 165 | int sharedX = 0; 166 | 167 | public MutableField Prop1 168 | { 169 | get { return new MutableField(sharedX++); } 170 | } 171 | 172 | public MutableField Prop2 173 | { 174 | get { return new MutableField(sharedX++); } 175 | } 176 | } 177 | 178 | 179 | class MutableField 180 | { 181 | int x; 182 | 183 | public MutableField(int x) 184 | { 185 | this.x = x; 186 | } 187 | } 188 | 189 | public void MethodWithTypeGenericArgsEval () 190 | { 191 | var a = new A("Just A"); 192 | var wrappedA = new Wrapper(new A("wrappedA")); 193 | var genericClass = new GenericClass(new A("Constructor arg A")); 194 | //genericClass.BaseMethodWithClassTArg (wrappedA); 195 | //genericClass.RetMethodWithClassTArg (a) 196 | Console.WriteLine("Break for MethodWithTypeGenericArgsEval");/*ba6350e5-7149-4cc2-a4cf-8a54c635eb38*/ 197 | } 198 | 199 | class A 200 | { 201 | public A(string myProp) 202 | { 203 | MyProp = myProp; 204 | } 205 | 206 | public string MyProp { get; set; } 207 | 208 | public override string ToString() 209 | { 210 | return MyProp; 211 | } 212 | } 213 | 214 | class GenericBaseClass 215 | { 216 | public readonly TBaseClassArg myArg; 217 | 218 | public GenericBaseClass(TBaseClassArg arg) 219 | { 220 | myArg = arg; 221 | } 222 | 223 | public TBaseClassArg BaseMethodWithClassTArg(TBaseClassArg arg) 224 | { 225 | return arg; 226 | } 227 | 228 | 229 | } 230 | 231 | class Wrapper 232 | { 233 | public TObj obj; 234 | 235 | public Wrapper(TObj obj) 236 | { 237 | this.obj = obj; 238 | } 239 | 240 | public override string ToString() 241 | { 242 | return string.Format("Wrapper({0})", obj); 243 | } 244 | } 245 | 246 | class GenericClass : GenericBaseClass> 247 | { 248 | public GenericClass(TOfClass arg) : base(new Wrapper(arg)) 249 | { 250 | } 251 | 252 | public void VoidMethodWithClassTArg(TOfClass tOfClass) {} 253 | public TOfClass RetMethodWithClassTArg(TOfClass tOfClass) {return tOfClass;} 254 | 255 | public void VoidMethodWithMethodTArg(TOfMethod tOfMethod) { } 256 | public void VoidMethodWithMethodAndClassTArg(TOfMethod tOfMethod, TOfClass tOfClass) { } 257 | 258 | } 259 | } 260 | } 261 | 262 | -------------------------------------------------------------------------------- /UnityDebug/UnityDebug.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | {D3E91D30-5B24-4743-BBE6-2EC62D7A2629} 7 | Exe 8 | UnityDebug 9 | UnityDebug 10 | v4.7.2 11 | 12 | 13 | 14 | 15 | true 16 | portable 17 | false 18 | ..\bin\ 19 | DEBUG; 20 | prompt 21 | 4 22 | x86 23 | false 24 | --unity-debug-extra-logging 25 | 26 | 27 | portable 28 | true 29 | ..\bin\ 30 | prompt 31 | 4 32 | true 33 | x86 34 | 35 | 36 | 37 | ..\External\atk-sharp.dll 38 | 39 | 40 | ..\External\CorApi.dll 41 | 42 | 43 | ..\External\CorApi2.dll 44 | 45 | 46 | ..\External\gdk-sharp.dll 47 | 48 | 49 | ..\External\glib-sharp.dll 50 | 51 | 52 | ..\External\gtk-sharp.dll 53 | 54 | 55 | ..\External\Mono.Addins.dll 56 | 57 | 58 | ..\External\Mono.Cairo.dll 59 | 60 | 61 | ..\External\Mono.Posix.dll 62 | 63 | 64 | False 65 | ..\External\Newtonsoft.Json.dll 66 | 67 | 68 | ..\External\pango-sharp.dll 69 | 70 | 71 | ..\External\SyntaxTree.VisualStudio.Unity.Messaging.dll 72 | 73 | 74 | 75 | 76 | ..\External\System.Composition.Convention.dll 77 | 78 | 79 | ..\External\System.Security.Cryptography.Algorithms.dll 80 | 81 | 82 | 83 | 84 | MonoDebug\DebugSession.cs 85 | 86 | 87 | MonoDebug\Handles.cs 88 | 89 | 90 | MonoDebug\MonoDebug.cs 91 | 92 | 93 | MonoDebug\Protocol.cs 94 | 95 | 96 | MonoDebug\Utilities.cs 97 | 98 | 99 | MonoDevelop.Debugger.Soft.Unity\UnityDebuggerSession.cs 100 | 101 | 102 | MonoDevelop.Debugger.Soft.Unity\UnityDebuggerStartInfo.cs 103 | 104 | 105 | 106 | 107 | 108 | MonoDevelop.Debugger.Soft.Unity\PlayerConnection.cs 109 | 110 | 111 | MonoDevelop.Debugger.Soft.Unity\UnityProcessDiscovery.cs 112 | 113 | 114 | MonoDevelop.Debugger.Soft.Unity\UnityProcessInfo.cs 115 | 116 | 117 | 118 | MonoDevelop.Debugger.Soft.Unity\UnityAttachInfo.cs 119 | 120 | 121 | 122 | MonoDevelop.Debugger.Soft.Unity\iOSOverUsbSupport.cs 123 | 124 | 125 | MonoDevelop.Debugger.Soft.Unity\Log.cs 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | {372e8e3e-29d5-4b4d-88a2-4711cd628c4e} 137 | Mono.Debugger.Soft 138 | 139 | 140 | {de40756e-57f6-4af2-b155-55e3a88cced8} 141 | Mono.Debugging.Soft 142 | 143 | 144 | {90c99adb-7d4b-4eb4-98c2-40bd1b14c7d2} 145 | Mono.Debugging 146 | 147 | 148 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/AdvancedEvaluationTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // AdvancedEvaluationTests.cs 3 | // 4 | // Author: 5 | // David Karlaš 6 | // 7 | // Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | using System; 27 | using System.Linq; 28 | using NUnit.Framework; 29 | 30 | namespace VSCode.UnityDebug.Tests 31 | { 32 | namespace Soft 33 | { 34 | [TestFixture] 35 | public class SdbAdvancedEvaluationAllowTargetInvokesTests : AdvancedEvaluationTests 36 | { 37 | public SdbAdvancedEvaluationAllowTargetInvokesTests () : base ("Mono.Debugger.Soft", true) 38 | { 39 | } 40 | } 41 | 42 | [TestFixture] 43 | public class SdbAdvancedEvaluationNoTargetInvokesTests : AdvancedEvaluationTests 44 | { 45 | public SdbAdvancedEvaluationNoTargetInvokesTests () : base ("Mono.Debugger.Soft", false) 46 | { 47 | } 48 | } 49 | } 50 | 51 | namespace Win32 52 | { 53 | [TestFixture] 54 | [Platform(Include = "Win")] 55 | public class CorAdvancedEvaluationAllowTargetInvokesTests : AdvancedEvaluationTests 56 | { 57 | public CorAdvancedEvaluationAllowTargetInvokesTests () : base ("MonoDevelop.Debugger.Win32", true) 58 | { 59 | } 60 | } 61 | 62 | [TestFixture] 63 | [Platform(Include = "Win")] 64 | public class CorAdvancedEvaluationNoTargetInvokesTests : AdvancedEvaluationTests 65 | { 66 | public CorAdvancedEvaluationNoTargetInvokesTests () : base ("MonoDevelop.Debugger.Win32", false) 67 | { 68 | } 69 | } 70 | } 71 | 72 | [TestFixture] 73 | public abstract class AdvancedEvaluationTests : DebugTests 74 | { 75 | protected AdvancedEvaluationTests (string de, bool allowTargetInvokes) : base (de) 76 | { 77 | AllowTargetInvokes = allowTargetInvokes; 78 | } 79 | 80 | [OneTimeSetUp] 81 | public override void SetUp () 82 | { 83 | base.SetUp (); 84 | Start ("AdvancedEvaluation"); 85 | } 86 | 87 | [Test] 88 | public void NamedTupleIndexMissmatch () 89 | { 90 | InitializeTest (); 91 | AddBreakpoint ("9196deef-9d41-41d6-bcef-9e3ef58f9635"); 92 | StartTest ("NamedTupleIndexMissmatchTest"); 93 | CheckPosition ("9196deef-9d41-41d6-bcef-9e3ef58f9635"); 94 | var val = Eval ("item.xmlNs"); 95 | Assert.AreEqual ("\"test\"", val.Value); 96 | Assert.AreEqual ("string", val.TypeName); 97 | } 98 | 99 | [Test] 100 | public void Bug24998 () 101 | { 102 | InitializeTest (); 103 | AddBreakpoint ("cc622137-a162-4b91-a85c-88241e68c3ea"); 104 | StartTest ("Bug24998Test"); 105 | CheckPosition ("cc622137-a162-4b91-a85c-88241e68c3ea"); 106 | var val = Eval ("someField"); 107 | Assert.AreEqual ("\"das\"", val.Value); 108 | Assert.AreEqual ("string", val.TypeName); 109 | 110 | val = Eval ("someVariable"); 111 | Assert.AreEqual ("System.Collections.ArrayList", val.TypeName); 112 | var children = val.GetAllChildrenSync (); 113 | Assert.AreEqual (2, children.Length); 114 | Assert.AreEqual ("[0]", children [0].ChildSelector); 115 | Assert.AreEqual ("1", children [0].Value); 116 | Assert.AreEqual ("int", children [0].TypeName); 117 | 118 | val = Eval ("action"); 119 | Assert.AreEqual ("System.Action", val.TypeName); 120 | } 121 | 122 | [Test] 123 | public void Bug33193 () 124 | { 125 | InitializeTest (); 126 | AddBreakpoint ("f1665382-7ddc-4c65-9c20-39d4a0ae9cf1"); 127 | StartTest ("Bug33193Test"); 128 | CheckPosition ("f1665382-7ddc-4c65-9c20-39d4a0ae9cf1"); 129 | Continue ("f1665382-7ddc-4c65-9c20-39d4a0ae9cf1"); 130 | var val = Eval ("item1"); 131 | Assert.AreEqual ("\"b\"", val.Value); 132 | Assert.AreEqual ("string", val.TypeName); 133 | } 134 | 135 | [Test] 136 | public void LocalFunctionVariablesTest () 137 | { 138 | InitializeTest (); 139 | AddBreakpoint ("07a0e6ef-e1d2-4f11-ab67-78e6ae5ea3bb"); 140 | StartTest ("LocalFunctionVariablesTest"); 141 | CheckPosition ("07a0e6ef-e1d2-4f11-ab67-78e6ae5ea3bb"); 142 | 143 | var val = Eval ("a"); 144 | Assert.AreEqual ("int", val.TypeName); 145 | Assert.AreEqual ("23", val.Value); 146 | 147 | var frame = Session.ActiveThread.Backtrace.GetFrame (0); 148 | var locals = frame.GetAllLocals (); 149 | Assert.AreEqual (4, locals.Length); 150 | 151 | val = locals.Single (l => l.Name == "a"); 152 | Assert.AreEqual ("int", val.TypeName); 153 | Assert.AreEqual ("23", val.Value); 154 | 155 | val = locals.Single (l => l.Name == "b"); 156 | Assert.AreEqual ("int", val.TypeName); 157 | Assert.AreEqual ("24", val.Value); 158 | 159 | val = locals.Single (l => l.Name == "c"); 160 | Assert.AreEqual ("string", val.TypeName); 161 | Assert.AreEqual ("\"hi\"", val.Value); 162 | 163 | val = locals.Single (l => l.Name == "d"); 164 | Assert.AreEqual ("int", val.TypeName); 165 | Assert.AreEqual ("25", val.Value); 166 | } 167 | 168 | [Test] 169 | public void LocalFunctionNoCaptureVariablesTest () 170 | { 171 | InitializeTest (); 172 | AddBreakpoint ("056bb4b5-1c7a-4e21-bd93-abd7389809d0"); 173 | StartTest ("LocalFunctionNoCaptureVariablesTest"); 174 | CheckPosition ("056bb4b5-1c7a-4e21-bd93-abd7389809d0"); 175 | 176 | var val = Eval ("a"); 177 | Assert.AreEqual ("int", val.TypeName); 178 | Assert.AreEqual ("17", val.Value); 179 | 180 | var frame = Session.ActiveThread.Backtrace.GetFrame (0); 181 | var locals = frame.GetAllLocals (); 182 | Assert.AreEqual (3, locals.Length); 183 | 184 | val = locals.Single (l => l.Name == "a"); 185 | Assert.AreEqual ("int", val.TypeName); 186 | Assert.AreEqual ("17", val.Value); 187 | 188 | val = locals.Single (l => l.Name == "b"); 189 | Assert.AreEqual ("int", val.TypeName); 190 | Assert.AreEqual ("23", val.Value); 191 | 192 | val = locals.Single (l => l.Name == "c"); 193 | Assert.AreEqual ("int", val.TypeName); 194 | Assert.AreEqual ("31", val.Value); 195 | } 196 | 197 | [Test] 198 | public void LocalFunctionCaptureDelegateVariablesTest () 199 | { 200 | InitializeTest (); 201 | AddBreakpoint ("94100486-d7c4-4239-9d87-ad61287117d5"); 202 | StartTest ("LocalFunctionCaptureDelegateVariablesTest"); 203 | CheckPosition ("94100486-d7c4-4239-9d87-ad61287117d5"); 204 | 205 | var val = Eval ("a"); 206 | Assert.AreEqual ("int", val.TypeName); 207 | Assert.AreEqual ("5", val.Value); 208 | 209 | var frame = Session.ActiveThread.Backtrace.GetFrame (0); 210 | var locals = frame.GetAllLocals (); 211 | Assert.AreEqual (2, locals.Length); 212 | 213 | val = locals.Single (l => l.Name == "a"); 214 | Assert.AreEqual ("int", val.TypeName); 215 | Assert.AreEqual ("5", val.Value); 216 | 217 | val = locals.Single (l => l.Name == "i"); 218 | Assert.AreEqual ("int", val.TypeName); 219 | Assert.AreEqual ("7", val.Value); 220 | } 221 | 222 | [Test] 223 | public void YieldMethodTest () 224 | { 225 | InitializeTest (); 226 | AddBreakpoint ("0b1212f8-9035-43dc-bf01-73efd078d680"); 227 | StartTest ("YieldMethodTest"); 228 | CheckPosition ("0b1212f8-9035-43dc-bf01-73efd078d680"); 229 | 230 | var val = Eval ("someVariable"); 231 | Assert.AreEqual ("System.Collections.ArrayList", val.TypeName); 232 | Assert.AreEqual (1, val.GetAllChildrenSync ().Length); 233 | 234 | AddBreakpoint ("e96b28bb-59bf-445d-b71f-316726ba4c52"); 235 | Continue ("e96b28bb-59bf-445d-b71f-316726ba4c52"); 236 | 237 | val = Eval ("someField"); 238 | Assert.AreEqual ("\"das1\"", val.Value); 239 | Assert.AreEqual ("string", val.TypeName); 240 | val = Eval ("someVariable"); 241 | Assert.AreEqual ("System.Collections.ArrayList", val.TypeName); 242 | Assert.AreEqual (2, val.GetAllChildrenSync ().Length); 243 | 244 | AddBreakpoint ("760feb92-176a-43d7-b5c9-116c4a3c6a6c"); 245 | Continue ("760feb92-176a-43d7-b5c9-116c4a3c6a6c"); 246 | 247 | val = Eval ("someField"); 248 | Assert.AreEqual ("\"das2\"", val.Value); 249 | Assert.AreEqual ("string", val.TypeName); 250 | val = Eval ("someVariable"); 251 | Assert.AreEqual ("System.Collections.ArrayList", val.TypeName); 252 | Assert.AreEqual (3, val.GetAllChildrenSync ().Length); 253 | 254 | AddBreakpoint ("a9a9aa9d-6b8b-4724-9741-2a3e1fb435e8"); 255 | Continue ("a9a9aa9d-6b8b-4724-9741-2a3e1fb435e8"); 256 | 257 | val = Eval ("someField"); 258 | Assert.AreEqual ("\"das2\"", val.Value); 259 | Assert.AreEqual ("string", val.TypeName); 260 | val = Eval ("someVariable"); 261 | Assert.AreEqual ("System.Collections.ArrayList", val.TypeName); 262 | Assert.AreEqual (3, val.GetAllChildrenSync ().Length); 263 | 264 | } 265 | 266 | [Test] 267 | public void InvocationsCountDuringExpandingTest () 268 | { 269 | InitializeTest (); 270 | AddBreakpoint ("8865cace-6b57-42cc-ad55-68a2c12dd3d7"); 271 | StartTest ("InvocationsCountDuringExpandingTest"); 272 | CheckPosition ("8865cace-6b57-42cc-ad55-68a2c12dd3d7"); 273 | var options = Session.EvaluationOptions.Clone (); 274 | options.GroupPrivateMembers = false; // to access private fields (else there are in Private subgroup) 275 | var value = Eval ("mutableFieldClass"); 276 | var sharedX = value.GetChildSync ("sharedX", options); 277 | Assert.NotNull (sharedX); 278 | 279 | var prop1 = value.GetChildSync("Prop1", options); 280 | Assert.NotNull (prop1); 281 | Assert.AreEqual ("UnityDebug.Tests.TestApp.AdvancedEvaluation.MutableField", prop1.TypeName); 282 | var prop1X = prop1.GetChildSync ("x", options); 283 | Assert.NotNull (prop1X); 284 | Assert.AreEqual ("0", prop1X.Value); // before CorValRef optimization this field evaluated to 2, 285 | // because every value to the root object was recalculated - this was wrong behavior 286 | 287 | var prop2 = value.GetChildSync ("Prop2", options); 288 | Assert.NotNull (prop2); 289 | var prop2X = prop2.GetChildSync("x", options); 290 | Assert.NotNull (prop2X); 291 | Assert.AreEqual ("1", prop2X.Value); 292 | 293 | Assert.AreEqual ("2", sharedX.Value); 294 | } 295 | 296 | [Test] 297 | public void MethodWithTypeGenericArgsEval () 298 | { 299 | InitializeTest (); 300 | AddBreakpoint ("ba6350e5-7149-4cc2-a4cf-8a54c635eb38"); 301 | StartTest ("MethodWithTypeGenericArgsEval"); 302 | CheckPosition ("ba6350e5-7149-4cc2-a4cf-8a54c635eb38"); 303 | 304 | var baseMethodEval = Eval ("genericClass.BaseMethodWithClassTArg (wrappedA)"); 305 | Assert.NotNull (baseMethodEval); 306 | Assert.AreEqual ("{Wrapper(wrappedA)}", baseMethodEval.Value); 307 | 308 | var thisMethodEval = Eval ("genericClass.RetMethodWithClassTArg (a)"); 309 | Assert.NotNull (thisMethodEval); 310 | Assert.AreEqual ("{Just A}", thisMethodEval.Value); 311 | } 312 | 313 | 314 | } 315 | } 316 | 317 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/DebugTests.cs: -------------------------------------------------------------------------------- 1 | // 2 | // DebugTests.cs 3 | // 4 | // Author: 5 | // Lluis Sanchez Gual 6 | // 7 | // Copyright (c) 2009 Novell, Inc (http://www.novell.com) 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | using System; 28 | using System.IO; 29 | using System.Threading; 30 | using System.Reflection; 31 | using System.Collections.Generic; 32 | using Mono.Debugging.Soft; 33 | using Mono.Debugging.Client; 34 | using Mono.Debugging.Tests; 35 | using NUnit.Framework; 36 | using StackFrame = Mono.Debugging.Client.StackFrame; 37 | 38 | namespace VSCode.UnityDebug.Tests 39 | { 40 | [TestFixture] 41 | public partial class DebugTests 42 | { 43 | const string TestAppExeName = "TestApp.exe"; 44 | const string TestAppProjectDirName = "UnityDebug.Tests.TestApp"; 45 | 46 | protected readonly ManualResetEvent targetStoppedEvent = new ManualResetEvent (false); 47 | readonly string EngineId; 48 | string TestName = ""; 49 | ITextFile SourceFile; 50 | 51 | SourceLocation lastStoppedPosition; 52 | 53 | public bool AllowTargetInvokes { get; protected set; } 54 | 55 | public DebuggerSession Session { get; private set; } 56 | 57 | public StackFrame Frame { get; private set; } 58 | 59 | protected DebugTests (string engineId) 60 | { 61 | EngineId = engineId; 62 | } 63 | 64 | // public virtual void IgnoreCorDebugger (string message = "") 65 | // { 66 | // if (!(Session is SoftDebuggerSession)) { 67 | // Assert.Ignore (message); 68 | // } 69 | // } 70 | // 71 | // public virtual void IgnoreSoftDebugger (string message = "") 72 | // { 73 | // if (Session is SoftDebuggerSession) { 74 | // Assert.Ignore (message); 75 | // } 76 | // } 77 | 78 | protected string TargetExeDirectory => Path.Combine(TargetProjectSourceDir, "bin", "Debug"); 79 | 80 | protected string TargetProjectSourceDir 81 | { 82 | get { 83 | string path = Directory.GetParent(Path.GetDirectoryName (GetType ().Assembly.Location)).Parent.Parent.FullName; 84 | return Path.Combine(path, TestAppProjectDirName); 85 | } 86 | } 87 | 88 | protected DebuggerSession CreateSession (string test, string engineId) 89 | { 90 | var session = new SoftDebuggerSession(); 91 | session.LogWriter = (stderr, text) => 92 | { 93 | if (stderr) 94 | Console.Error.WriteLine(text); 95 | else 96 | Console.Out.WriteLine(text); 97 | }; 98 | return session; 99 | } 100 | 101 | /// 102 | /// Reads file from given path 103 | /// 104 | /// 105 | /// 106 | public static ITextFile ReadFile (string sourcePath) 107 | { 108 | return new TextFile(MDTextFile.ReadFile (sourcePath)); 109 | } 110 | 111 | string m_MonoPath = ""; 112 | 113 | [OneTimeSetUp] 114 | public virtual void SetUp() 115 | { 116 | m_MonoPath = Environment.GetEnvironmentVariable("MONO_PATH"); 117 | Environment.SetEnvironmentVariable("MONO_PATH", @"C:\projects\mono\mono\build\builds\monodistribution\lib\mono\4.5"); 118 | } 119 | 120 | [OneTimeTearDown] 121 | public virtual void TearDown() 122 | { 123 | TearDownPartial (); 124 | if (Session != null) { 125 | Session.Exit (); 126 | Session.Dispose (); 127 | Session = null; 128 | } 129 | Environment.SetEnvironmentVariable("MONO_PATH", m_MonoPath); 130 | } 131 | 132 | partial void TearDownPartial (); 133 | 134 | protected virtual string TargetExePath 135 | { 136 | get{ 137 | return Path.Combine (TargetExeDirectory, TestAppExeName); 138 | } 139 | } 140 | 141 | protected virtual void Start (string test) 142 | { 143 | TestName = test; 144 | Session = CreateSession (test, EngineId); 145 | 146 | //var dsi = CreateStartInfo (test, EngineId); 147 | 148 | var assemblyName = AssemblyName.GetAssemblyName (TargetExePath); 149 | var soft = new SoftDebuggerStartInfo(null, new Dictionary()) 150 | { 151 | Command = TargetExePath, 152 | Arguments = test, 153 | UserAssemblyNames = new List { assemblyName }, 154 | }; 155 | ((SoftDebuggerLaunchArgs)soft.StartArgs).MonoExecutableFileName = @"C:\projects\mono\mono\build\builds\monodistribution\bin-x64\mono.exe"; 156 | 157 | if (soft != null) { 158 | } 159 | var ops = new DebuggerSessionOptions { 160 | ProjectAssembliesOnly = true, 161 | EvaluationOptions = EvaluationOptions.DefaultOptions 162 | }; 163 | ops.EvaluationOptions.AllowTargetInvoke = AllowTargetInvokes; 164 | ops.EvaluationOptions.EvaluationTimeout = 100000; 165 | 166 | 167 | var sourcePath = Path.Combine (TargetProjectSourceDir, test + ".cs"); 168 | SourceFile = ReadFile(sourcePath); 169 | AddBreakpoint ("break"); 170 | 171 | var done = new ManualResetEvent (false); 172 | 173 | Session.TargetHitBreakpoint += (sender, e) => { 174 | Frame = e.Backtrace.GetFrame (0); 175 | lastStoppedPosition = Frame.SourceLocation; 176 | targetStoppedEvent.Set (); 177 | done.Set (); 178 | }; 179 | 180 | Session.TargetExceptionThrown += (sender, e) => { 181 | Frame = e.Backtrace.GetFrame (0); 182 | for (int i = 0; i < e.Backtrace.FrameCount; i++) { 183 | if (!e.Backtrace.GetFrame (i).IsExternalCode) { 184 | Frame = e.Backtrace.GetFrame (i); 185 | break; 186 | } 187 | } 188 | lastStoppedPosition = Frame.SourceLocation; 189 | targetStoppedEvent.Set (); 190 | }; 191 | 192 | Session.TargetStopped += (sender, e) => { 193 | //This can be null in case of ForcedStop 194 | //which is called when exception is thrown 195 | //when Continue & Stepping is executed 196 | if (e.Backtrace != null) { 197 | Frame = e.Backtrace.GetFrame (0); 198 | lastStoppedPosition = Frame.SourceLocation; 199 | targetStoppedEvent.Set (); 200 | } else { 201 | Console.WriteLine ("e.Backtrace is null"); 202 | } 203 | }; 204 | 205 | var targetExited = new ManualResetEvent (false); 206 | Session.TargetExited += delegate { 207 | targetExited.Set (); 208 | }; 209 | 210 | Session.Run (soft, ops); 211 | Session.ExceptionHandler = (ex) => { 212 | Console.WriteLine ("Session.ExceptionHandler:" + Environment.NewLine + ex.ToString ()); 213 | HandleAnyException(ex); 214 | return true; 215 | }; 216 | switch (WaitHandle.WaitAny (new WaitHandle[]{ done, targetExited }, 3000)) { 217 | case 0: 218 | //Breakpoint is hit good... run tests now 219 | break; 220 | case 1: 221 | throw new Exception ("Test application exited before hitting breakpoint"); 222 | default: 223 | throw new Exception ("Timeout while waiting for initial breakpoint"); 224 | } 225 | if (Session is SoftDebuggerSession) { 226 | Console.WriteLine ("SDB protocol version:" + ((SoftDebuggerSession)Session).ProtocolVersion); 227 | } 228 | } 229 | 230 | void GetLineAndColumn (string breakpointMarker, int offset, string statement, out int line, out int col, ITextFile file) 231 | { 232 | int i = file.Text.IndexOf ("/*" + breakpointMarker + "*/", StringComparison.Ordinal); 233 | if (i == -1) 234 | Assert.Fail ("Break marker not found: " + breakpointMarker + " in " + file.Name); 235 | file.GetLineColumnFromPosition (i, out line, out col); 236 | line += offset; 237 | if (statement != null) { 238 | int lineStartPosition = file.GetPositionFromLineColumn (line, 1); 239 | string lineText = file.GetText (lineStartPosition, lineStartPosition + file.GetLineLength (line)); 240 | col = lineText.IndexOf (statement, StringComparison.Ordinal) + 1; 241 | if (col == 0) 242 | Assert.Fail ("Failed to find statement:" + statement + " at " + file.Name + "(" + line + ")"); 243 | } else { 244 | col = 1; 245 | } 246 | } 247 | 248 | public Breakpoint AddBreakpoint (string breakpointMarker, int offset = 0, string statement = null, ITextFile file = null) 249 | { 250 | file = file ?? SourceFile; 251 | int col, line; 252 | GetLineAndColumn (breakpointMarker, offset, statement, out line, out col, file); 253 | var bp = new Breakpoint (file.Name, line, col); 254 | Session.Breakpoints.Add (bp); 255 | return bp; 256 | } 257 | 258 | public void RunToCursor (string breakpointMarker, int offset = 0, string statement = null, ITextFile file = null) 259 | { 260 | file = file ?? SourceFile; 261 | int col, line; 262 | GetLineAndColumn (breakpointMarker, offset, statement, out line, out col, file); 263 | targetStoppedEvent.Reset (); 264 | Session.Breakpoints.RemoveRunToCursorBreakpoints (); 265 | var bp = new RunToCursorBreakpoint (file.Name, line, col); 266 | Session.Breakpoints.Add (bp); 267 | Session.Continue (); 268 | CheckPosition (breakpointMarker, offset, statement); 269 | } 270 | 271 | public void InitializeTest () 272 | { 273 | Session.Breakpoints.Clear (); 274 | Session.Options.EvaluationOptions = EvaluationOptions.DefaultOptions; 275 | Session.Options.ProjectAssembliesOnly = true; 276 | Session.Options.StepOverPropertiesAndOperators = false; 277 | AddBreakpoint ("break"); 278 | while (!CheckPosition ("break", 0, silent: true)) { 279 | targetStoppedEvent.Reset (); 280 | Session.Continue (); 281 | } 282 | } 283 | 284 | public ObjectValue Eval (string exp) 285 | { 286 | return Frame.GetExpressionValue (exp, true).Sync (); 287 | } 288 | 289 | public void WaitStop (int miliseconds) 290 | { 291 | if (!targetStoppedEvent.WaitOne (miliseconds)) { 292 | Assert.Fail ("WaitStop failure: Target stop timeout"); 293 | } 294 | } 295 | 296 | public bool CheckPosition (string guid, int offset = 0, string statement = null, bool silent = false, ITextFile file = null) 297 | { 298 | file = file ?? SourceFile; 299 | if (!targetStoppedEvent.WaitOne (6000)) { 300 | if (!silent) 301 | Assert.Fail ("CheckPosition failure: Target stop timeout"); 302 | return false; 303 | } 304 | if (lastStoppedPosition.FileName == file.Name) { 305 | int i = file.Text.IndexOf ("/*" + guid + "*/", StringComparison.Ordinal); 306 | if (i == -1) { 307 | if (!silent) 308 | Assert.Fail ("CheckPosition failure: Guid marker not found:" + guid + " in file:" + file.Name); 309 | return false; 310 | } 311 | int line, col; 312 | file.GetLineColumnFromPosition (i, out line, out col); 313 | if ((line + offset) != lastStoppedPosition.Line) { 314 | if (!silent) 315 | Assert.Fail ("CheckPosition failure: Wrong line Expected:" + (line + offset) + " Actual:" + lastStoppedPosition.Line + " in file:" + file.Name); 316 | return false; 317 | } 318 | if (!string.IsNullOrEmpty (statement)) { 319 | int position = file.GetPositionFromLineColumn (lastStoppedPosition.Line, lastStoppedPosition.Column); 320 | string actualStatement = file.GetText (position, position + statement.Length); 321 | if (statement != actualStatement) { 322 | if (!silent) 323 | Assert.AreEqual (statement, actualStatement); 324 | return false; 325 | } 326 | } 327 | } else { 328 | if (!silent) 329 | Assert.Fail ("CheckPosition failure: Wrong file Excpected:" + file.Name + " Actual:" + lastStoppedPosition.FileName); 330 | return false; 331 | } 332 | return true; 333 | } 334 | 335 | public void StepIn (string guid, string statement) 336 | { 337 | StepIn (guid, 0, statement); 338 | } 339 | 340 | public void StepIn (string guid, int offset = 0, string statement = null) 341 | { 342 | targetStoppedEvent.Reset (); 343 | Session.StepInstruction (); 344 | CheckPosition (guid, offset, statement); 345 | } 346 | 347 | public void StepOver (string guid, string statement) 348 | { 349 | StepOver (guid, 0, statement); 350 | } 351 | 352 | public void StepOver (string guid, int offset = 0, string statement = null) 353 | { 354 | targetStoppedEvent.Reset (); 355 | Session.NextInstruction (); 356 | CheckPosition (guid, offset, statement); 357 | } 358 | 359 | public void StepOut (string guid, string statement) 360 | { 361 | StepOut (guid, 0, statement); 362 | } 363 | 364 | public void StepOut (string guid, int offset = 0, string statement = null) 365 | { 366 | targetStoppedEvent.Reset (); 367 | Session.Finish (); 368 | CheckPosition (guid, offset, statement); 369 | } 370 | 371 | public void Continue (string guid, string statement) 372 | { 373 | Continue (guid, 0, statement); 374 | } 375 | 376 | public void Continue (string guid, int offset = 0, string statement = null, ITextFile file = null) 377 | { 378 | targetStoppedEvent.Reset (); 379 | Session.Continue (); 380 | CheckPosition(guid, offset, statement, file: file); 381 | } 382 | 383 | public void StartTest (string methodName) 384 | { 385 | if (!targetStoppedEvent.WaitOne (3000)) { 386 | Assert.Fail ("StartTest failure: Target stop timeout"); 387 | } 388 | Assert.AreEqual ('"' + methodName + '"', Eval ("NextMethodToCall = \"" + methodName + "\";").Value); 389 | targetStoppedEvent.Reset (); 390 | Session.Continue (); 391 | } 392 | 393 | public void SetNextStatement (string guid, int offset = 0, string statement = null, ITextFile file = null) 394 | { 395 | file = file ?? SourceFile; 396 | int line, column; 397 | GetLineAndColumn (guid, offset, statement, out line, out column, file); 398 | Session.SetNextStatement (file.Name, line, column); 399 | } 400 | 401 | public void AddCatchpoint (string exceptionName, bool includeSubclasses) 402 | { 403 | Session.Breakpoints.Add (new Catchpoint (exceptionName, includeSubclasses)); 404 | } 405 | 406 | partial void HandleAnyException(Exception exception); 407 | } 408 | 409 | static class EvalHelper 410 | { 411 | public static bool AtLeast (this Version ver, int major, int minor) { 412 | if ((ver.Major > major) || ((ver.Major == major && ver.Minor >= minor))) 413 | return true; 414 | else 415 | return false; 416 | } 417 | 418 | public static ObjectValue Sync (this ObjectValue val) 419 | { 420 | if (!val.IsEvaluating) 421 | return val; 422 | 423 | object locker = new object (); 424 | EventHandler h = delegate { 425 | lock (locker) { 426 | Monitor.PulseAll (locker); 427 | } 428 | }; 429 | 430 | val.ValueChanged += h; 431 | 432 | lock (locker) { 433 | while (val.IsEvaluating) { 434 | if (!Monitor.Wait (locker, 8000)) 435 | throw new Exception ("Timeout while waiting for value evaluation"); 436 | } 437 | } 438 | 439 | val.ValueChanged -= h; 440 | return val; 441 | } 442 | 443 | public static ObjectValue GetChildSync (this ObjectValue val, string name, EvaluationOptions ops) 444 | { 445 | var result = val.GetChild (name, ops); 446 | 447 | return result != null ? result.Sync () : null; 448 | } 449 | 450 | public static ObjectValue[] GetAllChildrenSync (this ObjectValue val) 451 | { 452 | var children = val.GetAllChildren (); 453 | foreach (var child in children) { 454 | child.Sync (); 455 | } 456 | return children; 457 | } 458 | } 459 | } 460 | -------------------------------------------------------------------------------- /Tests/UnityDebug.Tests/MDTextFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace Mono.Debugging.Tests 8 | { 9 | public class MDTextFile : IMDTextFile 10 | { 11 | const string LIBGLIB = "libglib-2.0-0.dll"; 12 | 13 | string name; 14 | StringBuilder text; 15 | string sourceEncoding; 16 | bool modified; 17 | 18 | public MDTextFile() { } 19 | 20 | public MDTextFile(string name) 21 | { 22 | Read(name); 23 | } 24 | 25 | public void Read(string fileName) 26 | { 27 | Read(fileName, null); 28 | } 29 | 30 | public static MDTextFile ReadFile(string fileName) 31 | { 32 | MDTextFile tf = new MDTextFile(); 33 | tf.Read(fileName); 34 | return tf; 35 | } 36 | 37 | public static MDTextFile ReadFile(string fileName, string encoding) 38 | { 39 | MDTextFile tf = new MDTextFile(); 40 | tf.Read(fileName, encoding); 41 | return tf; 42 | } 43 | 44 | public static MDTextFile ReadFile(string path, Stream content) 45 | { 46 | MDTextFile tf = new MDTextFile(); 47 | tf.name = path; 48 | tf.Read(content, null); 49 | return tf; 50 | } 51 | 52 | public void Read(Stream stream, string encoding) 53 | { 54 | byte[] content = null; 55 | long nread; 56 | 57 | retry: 58 | stream.Seek(0, SeekOrigin.Begin); 59 | 60 | if (encoding == null) 61 | { 62 | stream.Seek(0, SeekOrigin.Begin); 63 | } 64 | 65 | content = new byte [stream.Length]; 66 | nread = 0; 67 | 68 | int n; 69 | while ((n = stream.Read(content, (int)nread, (content.Length - (int)nread))) > 0) 70 | nread += n; 71 | 72 | if (encoding != null) 73 | { 74 | string s = ConvertFromEncoding(content, nread, encoding); 75 | if (s == null) 76 | { 77 | // The encoding provided was wrong, fall back to trying to use the BOM if it exists... 78 | encoding = null; 79 | content = null; 80 | goto retry; 81 | } 82 | 83 | text = new StringBuilder(s); 84 | sourceEncoding = encoding; 85 | return; 86 | } 87 | 88 | // Fall back to trying all the encodings... 89 | { 90 | string s = ConvertFromEncoding(content, nread, "UTF-8"); 91 | if (s != null) 92 | { 93 | sourceEncoding = "UTF-8"; 94 | text = new StringBuilder(s); 95 | return; 96 | } 97 | } 98 | throw new Exception("Unknown text file encoding"); 99 | } 100 | 101 | public void Read(string fileName, string encoding) 102 | { 103 | // Reads the file using the specified encoding. 104 | // If the encoding is null, it autodetects the 105 | // required encoding. 106 | 107 | this.name = fileName; 108 | 109 | using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 110 | { 111 | Read(stream, encoding); 112 | } 113 | } 114 | 115 | public static string GetFileEncoding(string fileName) 116 | { 117 | // Maybe this can be optimized later. 118 | MDTextFile file = MDTextFile.ReadFile(fileName); 119 | return file.SourceEncoding; 120 | } 121 | 122 | #region g_convert 123 | 124 | static string ConvertFromEncoding(byte[] content, long nread, string fromEncoding) 125 | { 126 | try 127 | { 128 | return Encoding.UTF8.GetString(ConvertToBytes(content, nread, "UTF-8", fromEncoding)); 129 | } 130 | catch (Exception e) 131 | { 132 | Console.WriteLine($"{fromEncoding}: failed to use. Exception: {e.Message}"); 133 | return null; 134 | } 135 | } 136 | 137 | struct GError 138 | { 139 | #pragma warning disable 649 140 | public int Domain; 141 | public int Code; 142 | public IntPtr Msg; 143 | #pragma warning restore 649 144 | } 145 | 146 | static unsafe int strlen(IntPtr str) 147 | { 148 | byte* s = (byte*)str; 149 | int n = 0; 150 | 151 | while (*s != 0) 152 | { 153 | s++; 154 | n++; 155 | } 156 | 157 | return n; 158 | } 159 | 160 | public static string Utf8PtrToString(IntPtr ptr) 161 | { 162 | if (ptr == IntPtr.Zero) 163 | return null; 164 | 165 | int len = strlen(ptr); 166 | byte[] bytes = new byte [len]; 167 | Marshal.Copy(ptr, bytes, 0, len); 168 | return System.Text.Encoding.UTF8.GetString(bytes); 169 | } 170 | 171 | static byte[] ConvertToBytes(byte[] content, long nread, string toEncoding, string fromEncoding) 172 | { 173 | if (nread > int.MaxValue) 174 | throw new Exception("Content too large."); 175 | if (toEncoding == fromEncoding) 176 | { 177 | if (content.LongLength == nread) 178 | return content; 179 | byte[] result = new byte[nread]; 180 | Array.Copy(content, result, nread); 181 | return result; 182 | } 183 | 184 | IntPtr nr = IntPtr.Zero, nw = IntPtr.Zero; 185 | IntPtr clPtr = new IntPtr(nread); 186 | IntPtr errptr = IntPtr.Zero; 187 | 188 | IntPtr cc = g_convert(content, clPtr, toEncoding, fromEncoding, ref nr, ref nw, ref errptr); 189 | if (cc != IntPtr.Zero) 190 | { 191 | //FIXME: check for out-of-range conversions on uints 192 | int len = (int)(uint)nw.ToInt64(); 193 | byte[] buf = new byte [len]; 194 | System.Runtime.InteropServices.Marshal.Copy(cc, buf, 0, buf.Length); 195 | g_free(cc); 196 | return buf; 197 | } 198 | else 199 | { 200 | GError err = (GError)Marshal.PtrToStructure(errptr, typeof(GError)); 201 | string reason = Utf8PtrToString(err.Msg); 202 | string message = string.Format("Failed to convert content from {0} to {1}: {2}.", fromEncoding, toEncoding, reason); 203 | InvalidEncodingException ex = new InvalidEncodingException(message); 204 | g_error_free(errptr); 205 | throw ex; 206 | } 207 | } 208 | 209 | [DllImport(LIBGLIB, CallingConvention = CallingConvention.Cdecl)] 210 | 211 | //note: textLength is signed, read/written are not 212 | static extern IntPtr g_convert(byte[] text, IntPtr textLength, string toCodeset, string fromCodeset, 213 | ref IntPtr read, ref IntPtr written, ref IntPtr err); 214 | 215 | [DllImport(LIBGLIB, CallingConvention = CallingConvention.Cdecl)] 216 | static extern void g_free(IntPtr ptr); 217 | 218 | [DllImport(LIBGLIB, CallingConvention = CallingConvention.Cdecl)] 219 | static extern void g_error_free(IntPtr err); 220 | 221 | #endregion 222 | 223 | public string Name 224 | { 225 | get { return name; } 226 | } 227 | 228 | public bool Modified 229 | { 230 | get { return modified; } 231 | } 232 | 233 | public string SourceEncoding 234 | { 235 | get { return sourceEncoding; } 236 | set { sourceEncoding = value; } 237 | } 238 | 239 | public string Text 240 | { 241 | get { return text.ToString(); } 242 | set 243 | { 244 | text = new StringBuilder(value); 245 | modified = true; 246 | } 247 | } 248 | 249 | public int Length 250 | { 251 | get { return text.Length; } 252 | } 253 | 254 | public string GetText(int startPosition, int endPosition) 255 | { 256 | return text.ToString(startPosition, endPosition - startPosition); 257 | } 258 | 259 | public char GetCharAt(int position) 260 | { 261 | if (position < text.Length) 262 | return text[position]; 263 | else 264 | return (char)0; 265 | } 266 | 267 | public int GetPositionFromLineColumn(int line, int column) 268 | { 269 | int lin = 1; 270 | int col = 1; 271 | for (int i = 0; i < text.Length && lin <= line; i++) 272 | { 273 | if (line == lin && column == col) 274 | return i; 275 | if (text[i] == '\r') 276 | { 277 | if (i + 1 < text.Length && text[i + 1] == '\n') 278 | i++; 279 | lin++; 280 | col = 1; 281 | } 282 | else if (text[i] == '\n') 283 | { 284 | lin++; 285 | col = 1; 286 | } 287 | else 288 | col++; 289 | } 290 | 291 | return -1; 292 | } 293 | 294 | public void GetLineColumnFromPosition(int position, out int line, out int column) 295 | { 296 | int lin = 1; 297 | int col = 1; 298 | for (int i = 0; i < position; i++) 299 | { 300 | if (text[i] == '\r') 301 | { 302 | if (i + 1 < position && text[i + 1] == '\n') 303 | i++; 304 | lin++; 305 | col = 1; 306 | } 307 | else if (text[i] == '\n') 308 | { 309 | lin++; 310 | col = 1; 311 | } 312 | else 313 | col++; 314 | } 315 | 316 | line = lin; 317 | column = col; 318 | } 319 | 320 | public int GetLineLength(int line) 321 | { 322 | int pos = GetPositionFromLineColumn(line, 1); 323 | if (pos == -1) return 0; 324 | int len = 0; 325 | while (pos < text.Length && text[pos] != '\n' && text[pos] != '\r') 326 | { 327 | pos++; 328 | len++; 329 | } 330 | 331 | return len; 332 | } 333 | 334 | public int InsertText(int position, string textIn) 335 | { 336 | text.Insert(position, textIn); 337 | modified = true; 338 | return textIn != null ? textIn.Length : 0; 339 | } 340 | 341 | public void DeleteText(int position, int length) 342 | { 343 | text.Remove(position, length); 344 | modified = true; 345 | } 346 | 347 | public bool Save() 348 | { 349 | var result = WriteFile(name, text.ToString(), sourceEncoding); 350 | modified = false; 351 | return result; 352 | } 353 | 354 | public static bool WriteFile(string fileName, byte[] content, string encoding, bool onlyIfChanged) 355 | { 356 | int contentLength = content.Length; 357 | byte[] converted; 358 | 359 | if (encoding != null) 360 | converted = ConvertToBytes(content, content.LongLength, encoding, "UTF-8"); 361 | else 362 | converted = content; 363 | 364 | if (onlyIfChanged) 365 | { 366 | FileInfo finfo = new FileInfo(fileName); 367 | if (finfo.Exists && finfo.Length == contentLength) 368 | { 369 | bool changed = false; 370 | 371 | // Open the file on disk and compare them byte by byte... 372 | using (FileStream stream = finfo.Open(FileMode.Open, FileAccess.Read, FileShare.Read)) 373 | { 374 | byte[] buf = new byte [4096]; 375 | int offset = 0; 376 | int nread; 377 | int i; 378 | 379 | while (!changed && (nread = stream.Read(buf, 0, buf.Length)) > 0) 380 | { 381 | i = 0; 382 | 383 | while (i < nread && offset < converted.Length) 384 | { 385 | if (converted[offset] != buf[i]) 386 | { 387 | changed = true; 388 | break; 389 | } 390 | 391 | offset++; 392 | i++; 393 | } 394 | 395 | if (offset == converted.Length && i < nread) 396 | changed = true; 397 | } 398 | 399 | if (offset < converted.Length) 400 | changed = true; 401 | } 402 | 403 | if (!changed) 404 | return true; 405 | } 406 | 407 | // Content has changed... 408 | } 409 | 410 | string tempName = Path.GetDirectoryName(fileName) + 411 | Path.DirectorySeparatorChar + ".#" + Path.GetFileName(fileName); 412 | 413 | using (FileStream fs = new FileStream(tempName, FileMode.Create, FileAccess.Write)) 414 | { 415 | fs.Write(converted, 0, converted.Length); 416 | } 417 | 418 | File.Move(tempName, fileName); 419 | return true; 420 | } 421 | 422 | public static bool WriteFile(string fileName, string content, string encoding, bool onlyIfChanged) 423 | { 424 | byte[] buf = Encoding.UTF8.GetBytes(content); 425 | return WriteFile(fileName, buf, encoding, onlyIfChanged); 426 | } 427 | 428 | public static bool WriteFile(string fileName, string content, string encoding) 429 | { 430 | return WriteFile(fileName, content, encoding, false); 431 | } 432 | } 433 | 434 | [Serializable] 435 | public class InvalidEncodingException : Exception 436 | { 437 | /// 438 | /// Initializes a new instance of the class 439 | /// 440 | public InvalidEncodingException() { } 441 | 442 | /// 443 | /// Initializes a new instance of the class 444 | /// 445 | /// A that describes the exception. 446 | public InvalidEncodingException(string message) 447 | : base(message) { } 448 | 449 | /// 450 | /// Initializes a new instance of the class 451 | /// 452 | /// A that describes the exception. 453 | /// The exception that is the cause of the current exception. 454 | public InvalidEncodingException(string message, Exception inner) 455 | : base(message, inner) { } 456 | } 457 | 458 | public static class ExtensionMethods 459 | { 460 | public static bool StartsWith(this IEnumerable t, IEnumerable s) 461 | { 462 | using (IEnumerator te = t.GetEnumerator()) 463 | { 464 | using (IEnumerator se = s.GetEnumerator()) 465 | { 466 | bool didMoveTe = false; 467 | while ((didMoveTe = te.MoveNext()) && se.MoveNext()) 468 | { 469 | if (!te.Current.Equals(se.Current)) 470 | return false; 471 | } 472 | 473 | return didMoveTe; 474 | } 475 | } 476 | } 477 | } 478 | } 479 | --------------------------------------------------------------------------------