diff --git a/CHANGELOG.md b/CHANGELOG.md index 898f78c..0daa3e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Code Editor Package for Visual Studio +## [2.0.22] - 2023-10-03 + +Integration: + +- Add support for `XDG_DATA_DIRS` and `.desktop` files on Linux for `VS Code` discovery. +- Use compile-time platform-specifics instead of using runtime conditions. + +Project generation: + +- Suppress `USG0001` warnings. +- Mark referenced assemblies as private (to not copy extra files to output directory when building). +- Add Unity capability to SDK-Style projects. +- Prevent circular dependency errors with SDK-Style projects. + + ## [2.0.21] - 2023-09-05 Integration: @@ -16,7 +31,6 @@ Project generation: - Add `visualstudiotoolsforunity.vstuc` entry to `extensions.json` when needed. - You can prevent the package from patching those configuration files by creating a `.vscode/.vstupatchdisable` file. - ## [2.0.20] - 2023-06-27 Integration: @@ -148,7 +162,7 @@ Documentation: Integration: -- Remove com.unity.nuget.newtonsoft-json dependency in favor of the built-in JsonUtility for the VS Test Runner. +- Remove `com.unity.nuget.newtonsoft-json` dependency in favor of the built-in JsonUtility for the VS Test Runner. ## [2.0.6] - 2021-01-20 @@ -186,7 +200,7 @@ Integration: Project generation: - Added C#8 language support. -- Added UnityProjectGeneratorVersion property. +- Added `UnityProjectGeneratorVersion` property. - Local and Embedded packages are now selected by default for generation. - Added support for asmdef root namespace. @@ -208,7 +222,7 @@ Integration: ## [2.0.1] - 2020-03-19 - When Visual Studio installation is compatible with C# 8.0, setup the language version to not prompt the user with unsupported constructs. (So far Unity only supports C# 7.3). -- Use Unity's TypeCache to improve project generation speed. +- Use Unity's `TypeCache` to improve project generation speed. - Properly check for a managed assembly before displaying a warning regarding legacy PDB usage. - Add support for selective project generation (embedded, local, registry, git, builtin, player). @@ -258,8 +272,8 @@ Integration: ## [1.0.4] - 2019-04-12 -- Fixing null reference issue for callbacks to AssetPostProcessor. -- Ensure Path.GetFullPath does not get an empty string. +- Fixing null reference issue for callbacks to `AssetPostProcessor`. +- Ensure `Path.GetFullPath` does not get an empty string. ## [1.0.3] - 2019-01-01 diff --git a/Editor/COMIntegration/Release/COMIntegration.exe b/Editor/COMIntegration/Release/COMIntegration.exe index 5788337..ff80992 100644 Binary files a/Editor/COMIntegration/Release/COMIntegration.exe and b/Editor/COMIntegration/Release/COMIntegration.exe differ diff --git a/Editor/Discovery.cs b/Editor/Discovery.cs index 98ea394..4144ae0 100644 --- a/Editor/Discovery.cs +++ b/Editor/Discovery.cs @@ -13,11 +13,13 @@ namespace Microsoft.Unity.VisualStudio.Editor { public static IEnumerable GetVisualStudioInstallations() { +#if UNITY_EDITOR_WIN foreach (var installation in VisualStudioForWindowsInstallation.GetVisualStudioInstallations()) yield return installation; - +#elif UNITY_EDITOR_OSX foreach (var installation in VisualStudioForMacInstallation.GetVisualStudioInstallations()) yield return installation; +#endif foreach (var installation in VisualStudioCodeInstallation.GetVisualStudioInstallations()) yield return installation; @@ -27,12 +29,13 @@ namespace Microsoft.Unity.VisualStudio.Editor { try { +#if UNITY_EDITOR_WIN if (VisualStudioForWindowsInstallation.TryDiscoverInstallation(editorPath, out installation)) return true; - +#elif UNITY_EDITOR_OSX if (VisualStudioForMacInstallation.TryDiscoverInstallation(editorPath, out installation)) return true; - +#endif if (VisualStudioCodeInstallation.TryDiscoverInstallation(editorPath, out installation)) return true; } @@ -46,8 +49,11 @@ namespace Microsoft.Unity.VisualStudio.Editor public static void Initialize() { +#if UNITY_EDITOR_WIN VisualStudioForWindowsInstallation.Initialize(); +#elif UNITY_EDITOR_OSX VisualStudioForMacInstallation.Initialize(); +#endif VisualStudioCodeInstallation.Initialize(); } } diff --git a/Editor/Messaging/UdpSocket.cs b/Editor/Messaging/UdpSocket.cs index f094780..414da7a 100644 --- a/Editor/Messaging/UdpSocket.cs +++ b/Editor/Messaging/UdpSocket.cs @@ -27,9 +27,7 @@ namespace Microsoft.Unity.VisualStudio.Editor.Messaging private void SetIOControl() { - if (!VisualStudioEditor.IsWindows) - return; - +#if UNITY_EDITOR_WIN try { const int SIO_UDP_CONNRESET = -1744830452; @@ -40,6 +38,7 @@ namespace Microsoft.Unity.VisualStudio.Editor.Messaging { // fallback } +#endif } public static byte[] BufferFor(IAsyncResult result) diff --git a/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration b/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration index 6965b8c..08aad61 100644 Binary files a/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration and b/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration differ diff --git a/Editor/ProjectGeneration/AssemblyNameProvider.cs b/Editor/ProjectGeneration/AssemblyNameProvider.cs index 6902843..5e568de 100644 --- a/Editor/ProjectGeneration/AssemblyNameProvider.cs +++ b/Editor/ProjectGeneration/AssemblyNameProvider.cs @@ -61,15 +61,18 @@ namespace Microsoft.Unity.VisualStudio.Editor return CompilationPipeline.GetAssemblyNameFromScriptPath(path); } + internal static readonly string AssemblyOutput = @"Temp\bin\Debug\".NormalizePathSeparators(); + internal static readonly string PlayerAssemblyOutput = @"Temp\bin\Debug\Player\".NormalizePathSeparators(); + public IEnumerable GetAssemblies(Func shouldFileBePartOfSolution) { - IEnumerable assemblies = GetAssembliesByType(AssembliesType.Editor, shouldFileBePartOfSolution, @"Temp\Bin\Debug\"); + IEnumerable assemblies = GetAssembliesByType(AssembliesType.Editor, shouldFileBePartOfSolution, AssemblyOutput); if (!ProjectGenerationFlag.HasFlag(ProjectGenerationFlag.PlayerAssemblies)) { return assemblies; } - var playerAssemblies = GetAssembliesByType(AssembliesType.Player, shouldFileBePartOfSolution, @"Temp\Bin\Debug\Player\"); + var playerAssemblies = GetAssembliesByType(AssembliesType.Player, shouldFileBePartOfSolution, PlayerAssemblyOutput); return assemblies.Concat(playerAssemblies); } @@ -98,7 +101,8 @@ namespace Microsoft.Unity.VisualStudio.Editor public string GetCompileOutputPath(string assemblyName) { - return assemblyName.EndsWith(".Player", StringComparison.Ordinal) ? @"Temp\Bin\Debug\Player\" : @"Temp\Bin\Debug\"; + // We need to keep this one for API surface check (AssemblyNameProvider is public), but not used anymore + throw new NotImplementedException(); } public IEnumerable GetAllAssetPaths() @@ -207,7 +211,10 @@ namespace Microsoft.Unity.VisualStudio.Editor public string GetAssemblyName(string assemblyOutputPath, string assemblyName) { - return assemblyOutputPath.EndsWith(@"\Player\", StringComparison.Ordinal) ? assemblyName + ".Player" : assemblyName; + if (assemblyOutputPath == PlayerAssemblyOutput) + return assemblyName + ".Player"; + + return assemblyName; } } } diff --git a/Editor/ProjectGeneration/LegacyStyleProjectGeneration.cs b/Editor/ProjectGeneration/LegacyStyleProjectGeneration.cs index 47cfdc1..0291129 100644 --- a/Editor/ProjectGeneration/LegacyStyleProjectGeneration.cs +++ b/Editor/ProjectGeneration/LegacyStyleProjectGeneration.cs @@ -12,6 +12,8 @@ namespace Microsoft.Unity.VisualStudio.Editor internal class LegacyStyleProjectGeneration : ProjectGeneration { + internal override string StyleName => "Legacy"; + public LegacyStyleProjectGeneration(string tempDirectory, IAssemblyNameProvider assemblyNameProvider, IFileIO fileIoProvider, IGUIDGenerator guidGenerator) : base(tempDirectory, assemblyNameProvider, fileIoProvider, guidGenerator) { } @@ -82,7 +84,7 @@ namespace Microsoft.Unity.VisualStudio.Editor internal override void GetProjectFooter(StringBuilder footerBuilder) { footerBuilder.Append(string.Join(k_WindowsNewline, - @" ", + $" ", @" ", @" ").Append(k_WindowsNewline); + + // Prevent circular dependency issues see https://github.com/microsoft/vscode-dotnettools/issues/401 + // We need a dedicated subfolder for each project in obj, else depending on the build order, nuget cache files could be overwritten + // We need to do this before common.props, else we'll have a MSB3539 The value of the property "BaseIntermediateOutputPath" was modified after it was used by MSBuild + headerBuilder.Append(@" ").Append(k_WindowsNewline); + headerBuilder.Append($" {@"Temp\obj\$(Configuration)\$(MSBuildProjectName)".NormalizePathSeparators()}").Append(k_WindowsNewline); + headerBuilder.Append(@" $(BaseIntermediateOutputPath)").Append(k_WindowsNewline); + headerBuilder.Append(@" ").Append(k_WindowsNewline); + + // Supported capabilities + GetCapabilityBlock(headerBuilder, "Sdk.props", "Include", SupportedCapabilities); + headerBuilder.Append(@" ").Append(k_WindowsNewline); headerBuilder.Append(@" false").Append(k_WindowsNewline); headerBuilder.Append(@" false").Append(k_WindowsNewline); @@ -76,7 +109,21 @@ namespace Microsoft.Unity.VisualStudio.Editor internal override void GetProjectFooter(StringBuilder footerBuilder) { + // Unsupported capabilities + GetCapabilityBlock(footerBuilder, "Sdk.targets", "Remove", UnsupportedCapabilities); + footerBuilder.Append("").Append(k_WindowsNewline); } + + internal static void GetCapabilityBlock(StringBuilder footerBuilder, string import, string attribute, string[] capabilities) + { + footerBuilder.Append($@" ").Append(k_WindowsNewline); + footerBuilder.Append(@" ").Append(k_WindowsNewline); + foreach (var capability in capabilities) + { + footerBuilder.Append($@" ").Append(k_WindowsNewline); + } + footerBuilder.Append(@" ").Append(k_WindowsNewline); + } } } diff --git a/Editor/VisualStudioCodeInstallation.cs b/Editor/VisualStudioCodeInstallation.cs index 7a1b5a5..aae57a6 100644 --- a/Editor/VisualStudioCodeInstallation.cs +++ b/Editor/VisualStudioCodeInstallation.cs @@ -66,13 +66,13 @@ namespace Microsoft.Unity.VisualStudio.Editor private static bool IsCandidateForDiscovery(string path) { - if (VisualStudioEditor.IsOSX) - return Directory.Exists(path) && Regex.IsMatch(path, ".*Code.*.app$", RegexOptions.IgnoreCase); - - if (VisualStudioEditor.IsWindows) - return File.Exists(path) && Regex.IsMatch(path, ".*Code.*.exe$", RegexOptions.IgnoreCase); - +#if UNITY_EDITOR_OSX + return Directory.Exists(path) && Regex.IsMatch(path, ".*Code.*.app$", RegexOptions.IgnoreCase); +#elif UNITY_EDITOR_WIN + return File.Exists(path) && Regex.IsMatch(path, ".*Code.*.exe$", RegexOptions.IgnoreCase); +#else return File.Exists(path) && path.EndsWith("code", StringComparison.OrdinalIgnoreCase); +#endif } [Serializable] @@ -99,17 +99,23 @@ namespace Microsoft.Unity.VisualStudio.Editor { var manifestBase = GetRealPath(editorPath); - if (VisualStudioEditor.IsWindows) // on Windows, editorPath is a file, resources as subdirectory - manifestBase = IOPath.GetDirectoryName(manifestBase); - else if (VisualStudioEditor.IsOSX) // on Mac, editorPath is a directory - manifestBase = IOPath.Combine(manifestBase, "Contents"); - else // on Linux, editorPath is a file, in a bin sub-directory - manifestBase = Directory.GetParent(manifestBase)?.Parent?.FullName; +#if UNITY_EDITOR_WIN + // on Windows, editorPath is a file, resources as subdirectory + manifestBase = IOPath.GetDirectoryName(manifestBase); +#elif UNITY_EDITOR_OSX + // on Mac, editorPath is a directory + manifestBase = IOPath.Combine(manifestBase, "Contents"); +#else + // on Linux, editorPath is a file, in a bin sub-directory + var parent = Directory.GetParent(manifestBase); + // but we can link to [vscode]/code or [vscode]/bin/code + manifestBase = parent?.Name == "bin" ? parent.Parent?.FullName : parent?.FullName; +#endif if (manifestBase == null) return false; - var manifestFullPath = IOPath.Combine(manifestBase, @"resources", "app", "package.json"); + var manifestFullPath = IOPath.Combine(manifestBase, "resources", "app", "package.json"); if (File.Exists(manifestFullPath)) { var manifest = JsonUtility.FromJson(File.ReadAllText(manifestFullPath)); @@ -138,30 +144,29 @@ namespace Microsoft.Unity.VisualStudio.Editor { var candidates = new List(); - if (VisualStudioEditor.IsWindows) - { - var localAppPath = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs"); - var programFiles = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); +#if UNITY_EDITOR_WIN + var localAppPath = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs"); + var programFiles = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); - foreach (var basePath in new[] {localAppPath, programFiles}) - { - candidates.Add(IOPath.Combine(basePath, "Microsoft VS Code", "Code.exe")); - candidates.Add(IOPath.Combine(basePath, "Microsoft VS Code Insiders", "Code - Insiders.exe")); - } - } - else if (VisualStudioEditor.IsOSX) + foreach (var basePath in new[] {localAppPath, programFiles}) { - var appPath = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); - candidates.AddRange(Directory.EnumerateDirectories(appPath, "Visual Studio Code*.app")); - } - else - { - candidates.Add("/usr/bin/code"); - candidates.Add("/bin/code"); - candidates.Add("/usr/local/bin/code"); + candidates.Add(IOPath.Combine(basePath, "Microsoft VS Code", "Code.exe")); + candidates.Add(IOPath.Combine(basePath, "Microsoft VS Code Insiders", "Code - Insiders.exe")); } +#elif UNITY_EDITOR_OSX + var appPath = IOPath.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles)); + candidates.AddRange(Directory.EnumerateDirectories(appPath, "Visual Studio Code*.app")); +#elif UNITY_EDITOR_LINUX + // Well known locations + candidates.Add("/usr/bin/code"); + candidates.Add("/bin/code"); + candidates.Add("/usr/local/bin/code"); - foreach (var candidate in candidates) + // Preference ordered base directories relative to which desktop files should be searched + candidates.AddRange(GetXdgCandidates()); +#endif + + foreach (var candidate in candidates.Distinct()) { if (TryDiscoverInstallation(candidate, out var installation)) yield return installation; @@ -169,6 +174,41 @@ namespace Microsoft.Unity.VisualStudio.Editor } #if UNITY_EDITOR_LINUX + private static readonly Regex DesktopFileExecEntry = new Regex(@"Exec=(\S+)", RegexOptions.Singleline | RegexOptions.Compiled); + + private static IEnumerable GetXdgCandidates() + { + var envdirs = Environment.GetEnvironmentVariable("XDG_DATA_DIRS"); + if (string.IsNullOrEmpty(envdirs)) + yield break; + + var dirs = envdirs.Split(':'); + foreach(var dir in dirs) + { + Match match = null; + + try + { + var desktopFile = IOPath.Combine(dir, "applications/code.desktop"); + if (!File.Exists(desktopFile)) + continue; + + var content = File.ReadAllText(desktopFile); + match = DesktopFileExecEntry.Match(content); + } + catch + { + // do not fail if we cannot read desktop file + } + + if (match == null || !match.Success) + continue; + + yield return match.Groups[1].Value; + break; + } + } + [System.Runtime.InteropServices.DllImport ("libc")] private static extern int readlink(string path, byte[] buffer, int buflen); @@ -475,13 +515,14 @@ namespace Microsoft.Unity.VisualStudio.Editor private static ProcessStartInfo ProcessStartInfoFor(string application, string arguments) { - if (!VisualStudioEditor.IsOSX) - return ProcessRunner.ProcessStartInfoFor(application, arguments, redirect: false); - +#if UNITY_EDITOR_OSX // wrap with built-in OSX open feature arguments = $"-n \"{application}\" --args {arguments}"; application = "open"; return ProcessRunner.ProcessStartInfoFor(application, arguments, redirect:false, shell: true); +#else + return ProcessRunner.ProcessStartInfoFor(application, arguments, redirect: false); +#endif } public static void Initialize() diff --git a/Editor/VisualStudioEditor.cs b/Editor/VisualStudioEditor.cs index a4f93ea..ed687c6 100644 --- a/Editor/VisualStudioEditor.cs +++ b/Editor/VisualStudioEditor.cs @@ -21,9 +21,6 @@ namespace Microsoft.Unity.VisualStudio.Editor [InitializeOnLoad] public class VisualStudioEditor : IExternalCodeEditor { - internal static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor; - internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == FileUtility.WinSeparator && Environment.NewLine == "\r\n"; - CodeEditor.Installation[] IExternalCodeEditor.Installations => _discoverInstallations .Result .Values diff --git a/Editor/VisualStudioForMacInstallation.cs b/Editor/VisualStudioForMacInstallation.cs index 5d9fb10..e8f7672 100644 --- a/Editor/VisualStudioForMacInstallation.cs +++ b/Editor/VisualStudioForMacInstallation.cs @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +#if UNITY_EDITOR_OSX + using System; using System.Collections.Generic; using System.Diagnostics; @@ -101,7 +103,7 @@ namespace Microsoft.Unity.VisualStudio.Editor private static bool IsCandidateForDiscovery(string path) { - return Directory.Exists(path) && VisualStudioEditor.IsOSX && Regex.IsMatch(path, "Visual\\s?Studio(?!.*Code.*).*.app$", RegexOptions.IgnoreCase); + return Directory.Exists(path) && Regex.IsMatch(path, "Visual\\s?Studio(?!.*Code.*).*.app$", RegexOptions.IgnoreCase); } public static bool TryDiscoverInstallation(string editorPath, out IVisualStudioInstallation installation) @@ -144,9 +146,6 @@ namespace Microsoft.Unity.VisualStudio.Editor public static IEnumerable GetVisualStudioInstallations() { - if (!VisualStudioEditor.IsOSX) - yield break; - var candidates = Directory.EnumerateDirectories("/Applications", "*.app"); foreach (var candidate in candidates) { @@ -178,3 +177,5 @@ namespace Microsoft.Unity.VisualStudio.Editor } } } + +#endif diff --git a/Editor/VisualStudioForWindowsInstallation.cs b/Editor/VisualStudioForWindowsInstallation.cs index 6138df2..862ecd8 100644 --- a/Editor/VisualStudioForWindowsInstallation.cs +++ b/Editor/VisualStudioForWindowsInstallation.cs @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +#if UNITY_EDITOR_WIN + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -126,7 +128,7 @@ namespace Microsoft.Unity.VisualStudio.Editor private static bool IsCandidateForDiscovery(string path) { - return File.Exists(path) && VisualStudioEditor.IsWindows && Regex.IsMatch(path, "devenv.exe$", RegexOptions.IgnoreCase); + return File.Exists(path) && Regex.IsMatch(path, "devenv.exe$", RegexOptions.IgnoreCase); } public static bool TryDiscoverInstallation(string editorPath, out IVisualStudioInstallation installation) @@ -169,9 +171,6 @@ namespace Microsoft.Unity.VisualStudio.Editor public static IEnumerable GetVisualStudioInstallations() { - if (!VisualStudioEditor.IsWindows) - yield break; - foreach (var installation in QueryVsWhere()) yield return installation; } @@ -373,8 +372,9 @@ namespace Microsoft.Unity.VisualStudio.Editor public static void Initialize() { - if (VisualStudioEditor.IsWindows) - _vsWherePath = FileUtility.GetPackageAssetFullPath("Editor", "VSWhere", "vswhere.exe"); + _vsWherePath = FileUtility.GetPackageAssetFullPath("Editor", "VSWhere", "vswhere.exe"); } } } + +#endif diff --git a/Editor/VisualStudioIntegration.cs b/Editor/VisualStudioIntegration.cs index 8ddc22a..29e94a8 100644 --- a/Editor/VisualStudioIntegration.cs +++ b/Editor/VisualStudioIntegration.cs @@ -106,10 +106,9 @@ namespace Microsoft.Unity.VisualStudio.Editor private static void RunOnShutdown(Action action) { // Mono on OSX has all kinds of quirks on AppDomain shutdown - if (!VisualStudioEditor.IsWindows) - return; - +#if UNITY_EDITOR_WIN AppDomain.CurrentDomain.DomainUnload += (_, __) => action(); +#endif } private static int DebuggingPort() diff --git a/package.json b/package.json index a7d9aaa..78ebf58 100644 --- a/package.json +++ b/package.json @@ -2,25 +2,25 @@ "name": "com.unity.ide.visualstudio", "displayName": "Visual Studio Editor", "description": "Code editor integration for supporting Visual Studio as code editor for unity. Adds support for generating csproj files for intellisense purposes, auto discovery of installations, etc.", - "version": "2.0.21", + "version": "2.0.22", "unity": "2019.4", "unityRelease": "25f1", "dependencies": { "com.unity.test-framework": "1.1.9" }, "relatedPackages": { - "com.unity.ide.visualstudio.tests": "2.0.21" + "com.unity.ide.visualstudio.tests": "2.0.22" }, "_upm": { - "changelog": "Integration:\n\n- Only disable the legacy `com.unity.ide.vscode` package going forward.\n- Fix json parsing issues with specific non-UTF code pages.\n\nProject generation:\n\n- Target `netstandard2.1` instead of `netstandard2.0`.\n- Set `defaultSolution` in `settings.json`.\n- Remove `files.exclude` entries for root `csproj` and `sln` files in `settings.json` when needed.\n- Add `vstuc` launch configuration to `launch.json` when needed.\n- Add `visualstudiotoolsforunity.vstuc` entry to `extensions.json` when needed.\n- You can prevent the package from patching those configuration files by creating a `.vscode/.vstupatchdisable` file." + "changelog": "Integration:\n\n- Add support for `XDG_DATA_DIRS` and `.desktop` files on Linux for `VS Code` discovery.\n- Use compile-time platform-specifics instead of using runtime conditions.\n\nProject generation:\n\n- Suppress `USG0001` warnings.\n- Mark referenced assemblies as private (to not copy extra files to output directory when building).\n- Add Unity capability to SDK-Style projects.\n- Prevent circular dependency errors with SDK-Style projects." }, "upmCi": { - "footprint": "33ecd838a074080a82176ca86b21c837ba396a28" + "footprint": "0b7347d4363afca9be389b61f0e25489ae3995b8" }, "documentationUrl": "https://docs.unity3d.com/Packages/com.unity.ide.visualstudio@2.0/manual/index.html", "repository": { "url": "https://github.cds.internal.unity3d.com/unity/com.unity.ide.visualstudio.git", "type": "git", - "revision": "eb2b500b99f6429d3d9dcb8acbcbd366dfbb42be" + "revision": "700b44077345e97d37d464ff25507638983aed64" } }