From fb1154211c94d6b12be31925716a2df3a4f0f655 Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity> Date: Wed, 6 Nov 2019 00:00:00 +0000 Subject: [PATCH] com.unity.ide.visualstudio@2.0.0 ## [2.0.0] - 2019-11-06 - Improved Visual Studio and Visual Studio for Mac automatic discovery - Added support for the VSTU messaging system (start/stop features from Visual Studio) - Added support for solution roundtrip (preserves references to external projects and solution properties) - Added support for VSTU Analyzers (requires Visual Studio 2019 16.3, Visual Studio for Mac 8.3) - Added a warning when using legacy pdb symbol files. - Fixed issues while Opening Visual Studio on Windows - Fixed issues while Opening Visual Studio on Mac ## [1.1.1] - 2019-05-29 Fix Bridge assembly loading with non VS2017 editors ## [1.1.0] - 2019-05-27 Move internal extension handling to package. --- CHANGELOG.md | 98 +- CHANGELOG.md.meta | 14 +- CONTRIBUTING.md | 10 +- CONTRIBUTING.md.meta | 14 +- Documentation~/README.md | 6 +- Editor.meta | 16 +- Editor/COMIntegration.meta | 16 +- Editor/COMIntegration/Release.meta | 16 +- .../COMIntegration/Release/COMIntegration.dom | Bin 51200 -> 0 bytes .../COMIntegration/Release/COMIntegration.exe | Bin 0 -> 383488 bytes ...ation.dom.meta => COMIntegration.exe.meta} | 14 +- Editor/Discovery.cs | 440 ++-- Editor/Discovery.cs.meta | 22 +- Editor/FileUtility.cs | 92 + .../{Utility.cs.meta => FileUtility.cs.meta} | 22 +- .../_CodeSignature.meta => Messaging.meta} | 16 +- Editor/Messaging/Deserializer.cs | 40 + .../Deserializer.cs.meta} | 22 +- Editor/Messaging/ExceptionEventArgs.cs | 18 + Editor/Messaging/ExceptionEventArgs.cs.meta | 11 + Editor/Messaging/Message.cs | 23 + Editor/Messaging/Message.cs.meta | 11 + Editor/Messaging/MessageEventArgs.cs | 19 + Editor/Messaging/MessageEventArgs.cs.meta | 11 + Editor/Messaging/MessageType.cs | 34 + Editor/Messaging/MessageType.cs.meta | 11 + Editor/Messaging/Messenger.cs | 176 ++ Editor/Messaging/Messenger.cs.meta | 11 + Editor/Messaging/Serializer.cs | 43 + Editor/Messaging/Serializer.cs.meta | 11 + Editor/Messaging/UdpSocket.cs | 53 + Editor/Messaging/UdpSocket.cs.meta | 11 + Editor/Plugins.meta | 16 +- ...meta => AppleEventIntegration.bundle.meta} | 56 +- .../Contents.meta | 16 +- .../Contents/Info.plist | 86 +- .../Contents/Info.plist.meta | 14 +- .../Contents/MacOS.meta | 16 +- .../Contents/MacOS/AppleEventIntegration | Bin 0 -> 19980 bytes .../MacOS/AppleEventIntegration.meta} | 14 +- .../MacOS/AppleEventIntegrationPlugin | Bin 34976 -> 0 bytes .../Contents/_CodeSignature/CodeResources | 115 - .../_CodeSignature/CodeResources.meta | 7 - Editor/ProjectGeneration.cs | 1918 +++++++++-------- Editor/ProjectGeneration.cs.meta | 22 +- Editor/Solution.cs | 12 + Editor/Solution.cs.meta | 11 + Editor/SolutionParser.cs | 80 + Editor/SolutionParser.cs.meta | 11 + Editor/SolutionProjectEntry.cs | 14 + Editor/SolutionProjectEntry.cs.meta | 11 + Editor/SolutionProperties.cs | 15 + Editor/SolutionProperties.cs.meta | 11 + Editor/Symbols.cs | 30 + Editor/Symbols.cs.meta | 11 + Editor/Utility.cs | 35 - Editor/VSEditor.cs | 335 --- Editor/VSInitializer.cs | 276 --- Editor/VSWhere.meta | 16 +- Editor/VSWhere/vswhere.exe.meta | 14 +- Editor/VisualStudioEditor.cs | 258 +++ ...tor.cs.meta => VisualStudioEditor.cs.meta} | 22 +- Editor/VisualStudioInstallation.cs | 126 ++ Editor/VisualStudioInstallation.cs.meta | 11 + Editor/VisualStudioIntegration.cs | 174 ++ Editor/VisualStudioIntegration.cs.meta | 11 + Editor/com.unity.ide.visualstudio.asmdef | 18 +- Editor/com.unity.ide.visualstudio.asmdef.meta | 14 +- LICENSE.md | 43 +- LICENSE.md.meta | 14 +- ThirdPartyNotices.md | 60 +- ThirdPartyNotices.md.meta | 14 +- package.json | 8 +- package.json.meta | 14 +- 74 files changed, 2944 insertions(+), 2306 deletions(-) delete mode 100644 Editor/COMIntegration/Release/COMIntegration.dom create mode 100644 Editor/COMIntegration/Release/COMIntegration.exe rename Editor/COMIntegration/Release/{COMIntegration.dom.meta => COMIntegration.exe.meta} (95%) create mode 100644 Editor/FileUtility.cs rename Editor/{Utility.cs.meta => FileUtility.cs.meta} (95%) rename Editor/{Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature.meta => Messaging.meta} (73%) create mode 100644 Editor/Messaging/Deserializer.cs rename Editor/{VSInitializer.cs.meta => Messaging/Deserializer.cs.meta} (80%) create mode 100644 Editor/Messaging/ExceptionEventArgs.cs create mode 100644 Editor/Messaging/ExceptionEventArgs.cs.meta create mode 100644 Editor/Messaging/Message.cs create mode 100644 Editor/Messaging/Message.cs.meta create mode 100644 Editor/Messaging/MessageEventArgs.cs create mode 100644 Editor/Messaging/MessageEventArgs.cs.meta create mode 100644 Editor/Messaging/MessageType.cs create mode 100644 Editor/Messaging/MessageType.cs.meta create mode 100644 Editor/Messaging/Messenger.cs create mode 100644 Editor/Messaging/Messenger.cs.meta create mode 100644 Editor/Messaging/Serializer.cs create mode 100644 Editor/Messaging/Serializer.cs.meta create mode 100644 Editor/Messaging/UdpSocket.cs create mode 100644 Editor/Messaging/UdpSocket.cs.meta rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle.meta => AppleEventIntegration.bundle.meta} (88%) rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle => AppleEventIntegration.bundle}/Contents.meta (73%) rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle => AppleEventIntegration.bundle}/Contents/Info.plist (76%) rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle => AppleEventIntegration.bundle}/Contents/Info.plist.meta (71%) rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle => AppleEventIntegration.bundle}/Contents/MacOS.meta (73%) create mode 100644 Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration rename Editor/Plugins/{AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin.meta => AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration.meta} (71%) delete mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin delete mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources delete mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta create mode 100644 Editor/Solution.cs create mode 100644 Editor/Solution.cs.meta create mode 100644 Editor/SolutionParser.cs create mode 100644 Editor/SolutionParser.cs.meta create mode 100644 Editor/SolutionProjectEntry.cs create mode 100644 Editor/SolutionProjectEntry.cs.meta create mode 100644 Editor/SolutionProperties.cs create mode 100644 Editor/SolutionProperties.cs.meta create mode 100644 Editor/Symbols.cs create mode 100644 Editor/Symbols.cs.meta delete mode 100644 Editor/Utility.cs delete mode 100644 Editor/VSEditor.cs delete mode 100644 Editor/VSInitializer.cs create mode 100644 Editor/VisualStudioEditor.cs rename Editor/{VSEditor.cs.meta => VisualStudioEditor.cs.meta} (95%) create mode 100644 Editor/VisualStudioInstallation.cs create mode 100644 Editor/VisualStudioInstallation.cs.meta create mode 100644 Editor/VisualStudioIntegration.cs create mode 100644 Editor/VisualStudioIntegration.cs.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3ad28..3795d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,40 +1,58 @@ -# Code Editor Package for Visual Studio - -## [1.0.11] - 2019-05-21 - -Fix detection of visual studio for mac installation. - -## [1.0.10] - 2019-05-04 - -Fix ignored comintegration executable - - -## [1.0.9] - 2019-03-05 - -Updated MonoDevelop support, to pass correct arguments, and not import VSTU plugin -Use release build of COMIntegration for Visual Studio - - -## [1.0.7] - 2019-04-30 - -Ensure asset database is refreshed when generating csproj and solution files. - -## [1.0.6] - 2019-04-27 - -Add support for generating all csproj files. - -## [1.0.5] - 2019-04-18 - -Fix relative package paths. -Fix opening editor on mac. - -## [1.0.4] - 2019-04-12 - -- Fixing null reference issue for callbacks to AssetPostProcessor. -- Ensure Path.GetFullPath does not get an empty string. - -## [1.0.3] - 2019-01-01 - -### This is the first release of *Unity Package visualstudio_editor*. - -Using the newly created api to integrate Visual Studio with Unity. +# Code Editor Package for Visual Studio + +## [2.0.0] - 2019-11-06 + +- Improved Visual Studio and Visual Studio for Mac automatic discovery +- Added support for the VSTU messaging system (start/stop features from Visual Studio) +- Added support for solution roundtrip (preserves references to external projects and solution properties) +- Added support for VSTU Analyzers (requires Visual Studio 2019 16.3, Visual Studio for Mac 8.3) +- Added a warning when using legacy pdb symbol files. +- Fixed issues while Opening Visual Studio on Windows +- Fixed issues while Opening Visual Studio on Mac + +## [1.1.1] - 2019-05-29 + +Fix Bridge assembly loading with non VS2017 editors + +## [1.1.0] - 2019-05-27 + +Move internal extension handling to package. + +## [1.0.11] - 2019-05-21 + +Fix detection of visual studio for mac installation. + +## [1.0.10] - 2019-05-04 + +Fix ignored comintegration executable + + +## [1.0.9] - 2019-03-05 + +Updated MonoDevelop support, to pass correct arguments, and not import VSTU plugin +Use release build of COMIntegration for Visual Studio + + +## [1.0.7] - 2019-04-30 + +Ensure asset database is refreshed when generating csproj and solution files. + +## [1.0.6] - 2019-04-27 + +Add support for generating all csproj files. + +## [1.0.5] - 2019-04-18 + +Fix relative package paths. +Fix opening editor on mac. + +## [1.0.4] - 2019-04-12 + +- Fixing null reference issue for callbacks to AssetPostProcessor. +- Ensure Path.GetFullPath does not get an empty string. + +## [1.0.3] - 2019-01-01 + +### This is the first release of *Unity Package visualstudio_editor*. + +Using the newly created api to integrate Visual Studio with Unity. diff --git a/CHANGELOG.md.meta b/CHANGELOG.md.meta index eb54a61..069c9bf 100644 --- a/CHANGELOG.md.meta +++ b/CHANGELOG.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 6022bdd5b2896a54f94123b812705321 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 6022bdd5b2896a54f94123b812705321 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f0005f6..6443a82 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -# Contributing - -## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement) -By making a pull request, you are confirming agreement to the terms and conditions of the UCA, including that your Contributions are your original creation and that you have complete right and authority to make your Contributions. - +# Contributing + +## All contributions are subject to the [Unity Contribution Agreement(UCA)](https://unity3d.com/legal/licenses/Unity_Contribution_Agreement) and [Microsoft Contributor License Agreement (CLA)](https://cla.opensource.microsoft.com/) +By making a pull request, you are confirming agreement to the terms and conditions of the UCA and CLA, including that your contributions are your original creation and that you have complete right and authority to make your contributions. + ## Once you have a change ready following these ground rules. Simply make a pull request \ No newline at end of file diff --git a/CONTRIBUTING.md.meta b/CONTRIBUTING.md.meta index 08fa9e7..61c088c 100644 --- a/CONTRIBUTING.md.meta +++ b/CONTRIBUTING.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: cd78ce5b75b8be84d8b94cd99903161f -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: cd78ce5b75b8be84d8b94cd99903161f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Documentation~/README.md b/Documentation~/README.md index 4b5de36..f2ae703 100644 --- a/Documentation~/README.md +++ b/Documentation~/README.md @@ -1,4 +1,4 @@ -# Code Editor Package for Visual Studio - -This package is not intended to be modified by users. +# Code Editor Package for Visual Studio + +This package is not intended to be modified by users. Nor does it provide any api intended to be included in user projects. \ No newline at end of file diff --git a/Editor.meta b/Editor.meta index 7b6d700..5683b3b 100644 --- a/Editor.meta +++ b/Editor.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 4a707af59e3522d43afe34dfc4429b86 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 4a707af59e3522d43afe34dfc4429b86 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/COMIntegration.meta b/Editor/COMIntegration.meta index c36cceb..bf3a993 100644 --- a/Editor/COMIntegration.meta +++ b/Editor/COMIntegration.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 36422aa067e092e45b9820da2ee3e728 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 36422aa067e092e45b9820da2ee3e728 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/COMIntegration/Release.meta b/Editor/COMIntegration/Release.meta index 3ebb587..c7e9b68 100644 --- a/Editor/COMIntegration/Release.meta +++ b/Editor/COMIntegration/Release.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 41b2d972bdac29e4a89ef08b3b52c248 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 41b2d972bdac29e4a89ef08b3b52c248 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/COMIntegration/Release/COMIntegration.dom b/Editor/COMIntegration/Release/COMIntegration.dom deleted file mode 100644 index 198a4120a77a4492770bea3995d7922af56cae46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51200 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 I_5a7`ztBXc#{d8T diff --git a/Editor/COMIntegration/Release/COMIntegration.exe b/Editor/COMIntegration/Release/COMIntegration.exe new file mode 100644 index 0000000000000000000000000000000000000000..a644e9583a5d104c842d64a789cbfaa08ec1c873 GIT binary patch literal 383488 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%0Dp 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 new CodeEditor.Installation - { - Path = pair.Value[0], - Name = VisualStudioVersionToNiceName(pair.Key) - }).ToArray(); - } - if (VSEditor.IsOSX) - { - var installationList = new List(); - AddIfDirectoryExists("Visual Studio", "/Applications/Visual Studio.app", installationList); - AddIfDirectoryExists("Visual Studio (Preview)", "/Applications/Visual Studio (Preview).app", installationList); - return installationList.ToArray(); - } - } - catch (Exception ex) - { - UnityEngine.Debug.Log($"Error detecting Visual Studio installations: {ex.Message}{Environment.NewLine}{ex.StackTrace}"); - } - return new CodeEditor.Installation[0]; - } - - void AddIfDirectoryExists(string name, string path, List installations) - { - if (Directory.Exists(path)) - { - installations.Add(new CodeEditor.Installation { Name = name, Path = path }); - } - } - - static string GetRegistryValue(string path, string key) - { - try - { - return Registry.GetValue(path, key, null) as string; - } - catch (Exception) - { - return ""; - } - } - - /// - /// Derives the Visual Studio installation path from the debugger path - /// - /// - /// The Visual Studio installation path (to devenv.exe) - /// - /// - /// The debugger path from the windows registry - /// - static string DeriveVisualStudioPath(string debuggerPath) - { - string startSentinel = DeriveProgramFilesSentinel(); - string endSentinel = "Common7"; - bool started = false; - string[] tokens = debuggerPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); - - string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); - - // Walk directories in debugger path, chop out "Program Files\INSTALLATION\PATH\HERE\Common7" - foreach (var token in tokens) - { - if (!started && string.Equals(startSentinel, token, StringComparison.OrdinalIgnoreCase)) - { - started = true; - continue; - } - if (started) - { - path = Path.Combine(path, token); - if (string.Equals(endSentinel, token, StringComparison.OrdinalIgnoreCase)) - break; - } - } - - return Path.Combine(path, "IDE", "devenv.exe"); - } - - /// - /// Derives the program files sentinel for grabbing the VS installation path. - /// - /// - /// From a path like 'c:\Archivos de programa (x86)', returns 'Archivos de programa' - /// - static string DeriveProgramFilesSentinel() - { - string path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) - .Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) - .LastOrDefault(); - - if (!string.IsNullOrEmpty(path)) - { - // This needs to be the "real" Program Files regardless of 64bitness - int index = path.LastIndexOf("(x86)"); - if (0 <= index) - path = path.Remove(index); - return path.TrimEnd(); - } - - return "Program Files"; - } - - public static void ParseRawDevEnvPaths(string[] rawDevEnvPaths, Dictionary versions) - { - if (rawDevEnvPaths == null) - { - return; - } - - var v2017 = rawDevEnvPaths.Where(path => path.Contains("2017")).ToArray(); - var v2019 = rawDevEnvPaths.Where(path => path.Contains("2019")).ToArray(); - - if (v2017.Length > 0) - { - versions[VisualStudioVersion.VisualStudio2017] = v2017; - } - - if (v2019.Length > 0) - { - versions[VisualStudioVersion.VisualStudio2019] = v2019; - } - } - - /// - /// Detects Visual Studio installations using the Windows registry - /// - /// - /// The detected Visual Studio installations - /// - public static Dictionary GetInstalledVisualStudios() - { - var versions = new Dictionary(); - - if (VSEditor.IsWindows) - { - foreach (VisualStudioVersion version in Enum.GetValues(typeof(VisualStudioVersion))) - { - if (version > VisualStudioVersion.VisualStudio2015) - continue; - - try - { - // Try COMNTOOLS environment variable first - FindLegacyVisualStudio(version, versions); - } - catch (Exception e) - { - UnityEngine.Debug.LogError($"VS: {e.Message}"); - } - } - - var raw = FindVisualStudioDevEnvPaths(); - - ParseRawDevEnvPaths(raw.ToArray(), versions); - } - - return versions; - } - - static void FindLegacyVisualStudio(VisualStudioVersion version, Dictionary versions) - { - string key = Environment.GetEnvironmentVariable($"VS{(int)version}0COMNTOOLS"); - if (!string.IsNullOrEmpty(key)) - { - string path = Path.Combine(key, "..", "IDE", "devenv.exe"); - if (File.Exists(path)) - { - versions[version] = new[] { path }; - return; - } - } - - // Try the proper registry key - key = GetRegistryValue( - $@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{(int)version}.0", "InstallDir"); - - // Try to fallback to the 32bits hive - if (string.IsNullOrEmpty(key)) - key = GetRegistryValue( - $@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\{(int)version}.0", "InstallDir"); - - if (!string.IsNullOrEmpty(key)) - { - string path = Path.Combine(key, "devenv.exe"); - if (File.Exists(path)) - { - versions[version] = new[] { path }; - return; - } - } - - // Fallback to debugger key - key = GetRegistryValue( - // VS uses this key for the local debugger path - $@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{(int)version}.0\Debugger", "FEQARuntimeImplDll"); - if (!string.IsNullOrEmpty(key)) - { - string path = DeriveVisualStudioPath(key); - if (!string.IsNullOrEmpty(path) && File.Exists(path)) - versions[version] = new[] { DeriveVisualStudioPath(key) }; - } - } - - static IEnumerable FindVisualStudioDevEnvPaths() - { - string asset = AssetDatabase.FindAssets("VSWhere a:packages").Select(AssetDatabase.GUIDToAssetPath).FirstOrDefault(assetPath => assetPath.Contains("vswhere.exe")); - if (string.IsNullOrWhiteSpace(asset)) // This may be called too early where the asset database has not replicated this information yet. - { - yield break; - } - UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(asset); - var progpath = packageInfo.resolvedPath + asset.Substring("Packages/com.unity.ide.visualstudio".Length); - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = progpath, - Arguments = "-prerelease -property productPath", - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - } - }; - - process.Start(); - process.WaitForExit(); - - while (!process.StandardOutput.EndOfStream) - { - yield return process.StandardOutput.ReadLine(); - } - } - } -} \ No newline at end of file +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Unity Technologies. + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.IO; +using System.Collections.Generic; +using UnityEngine; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Linq; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal static class Discovery + { + public static IEnumerable GetVisualStudioInstallations() + { + if (VisualStudioEditor.IsWindows) + { + foreach (var installation in QueryVsWhere()) + yield return installation; + } + + if (VisualStudioEditor.IsOSX) + { + var candidates = Directory.EnumerateDirectories("/Applications", "*.app"); + foreach (var candidate in candidates) + { + if (TryDiscoverInstallation(candidate, out var installation)) + yield return installation; + } + } + } + + private static bool IsCandidateToDiscovery(string path) + { + if (File.Exists(path) && VisualStudioEditor.IsWindows && Regex.IsMatch(path, "devenv.exe$", RegexOptions.IgnoreCase)) + return true; + + if (Directory.Exists(path) && VisualStudioEditor.IsOSX && Regex.IsMatch(path, "Visual\\s?Studio(?!.*Code.*).*.app$", RegexOptions.IgnoreCase)) + return true; + + return false; + } + + public static bool TryDiscoverInstallation(string editorPath, out VisualStudioInstallation installation) + { + installation = null; + + if (string.IsNullOrEmpty(editorPath)) + return false; + + if (!IsCandidateToDiscovery(editorPath)) + return false; + + // On windows we use the executable directly, so we can query extra information + var fvi = editorPath; + + // On Mac we use the .app folder, so we need to access to main assembly + if (VisualStudioEditor.IsOSX) + fvi = Path.Combine(editorPath, "Contents", "Resources", "lib", "monodevelop", "bin", "VisualStudio.exe"); + + if (!File.Exists(fvi)) + return false; + + // VS preview are not using the isPrerelease flag so far + // On Windows FileDescription contains "Preview", but not on Mac + var vi = FileVersionInfo.GetVersionInfo(fvi); + var version = new Version(vi.ProductVersion); + var isPrerelease = vi.IsPreRelease || string.Concat(editorPath, "/" + vi.FileDescription).ToLower().Contains("preview"); + + installation = new VisualStudioInstallation() + { + IsPrerelease = isPrerelease, + Name = $"{vi.FileDescription}{(isPrerelease && VisualStudioEditor.IsOSX ? " Preview" : string.Empty)} [{version.ToString(3)}]", + Path = editorPath, + Version = version + }; + return true; + } + + #region VsWhere Json Schema + #pragma warning disable CS0649 + [Serializable] + internal class VsWhereResult + { + public VsWhereEntry[] entries; + + public static VsWhereResult FromJson(string json) + { + return JsonUtility.FromJson("{ \"" + nameof(VsWhereResult.entries) + "\": " + json + " }"); + } + + public IEnumerable ToVisualStudioInstallations() + { + foreach(var entry in entries) + { + yield return new VisualStudioInstallation() + { + Name = $"{entry.displayName} [{entry.catalog.productDisplayVersion}]", + Path = entry.productPath, + IsPrerelease = entry.isPrerelease, + Version = Version.Parse(entry.catalog.buildVersion) + }; + } + } + } + + [Serializable] + internal class VsWhereEntry + { + public string displayName; + public bool isPrerelease; + public string productPath; + public VsWhereCatalog catalog; + } + + [Serializable] + internal class VsWhereCatalog + { + public string productDisplayVersion; // non parseable like "16.3.0 Preview 3.0" + public string buildVersion; + } + #pragma warning restore CS3021 + #endregion + + private static IEnumerable QueryVsWhere() + { + var progpath = FileUtility + .FindPackageAssetFullPath("VSWhere a:packages", "vswhere.exe") + .FirstOrDefault(); + + if (string.IsNullOrWhiteSpace(progpath)) + return Enumerable.Empty(); + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = progpath, + Arguments = "-prerelease -format json", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + } + }; + + using (process) + { + var json = string.Empty; + + process.OutputDataReceived += (o, e) => json += e.Data; + process.Start(); + process.BeginOutputReadLine(); + process.WaitForExit(); + + var result = VsWhereResult.FromJson(json); + return result.ToVisualStudioInstallations(); + } + } + } +} diff --git a/Editor/Discovery.cs.meta b/Editor/Discovery.cs.meta index 0dfad1c..0954edf 100644 --- a/Editor/Discovery.cs.meta +++ b/Editor/Discovery.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: abe003ac6fee32e4892100a78f555011 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: abe003ac6fee32e4892100a78f555011 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/FileUtility.cs b/Editor/FileUtility.cs new file mode 100644 index 0000000..9e04ac4 --- /dev/null +++ b/Editor/FileUtility.cs @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Unity Technologies. + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal static class FileUtility + { + public const char WinSeparator = '\\'; + public const char UnixSeparator = '/'; + + // Safe for packages as we use packageInfo.resolvedPath, so this should work in library package cache as well + public static string[] FindPackageAssetFullPath(string assetfilter, string filefilter) + { + return AssetDatabase.FindAssets(assetfilter) + .Select(AssetDatabase.GUIDToAssetPath) + .Where(assetPath => assetPath.Contains(filefilter)) + .Select(asset => + { + var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(asset); + return Normalize(packageInfo.resolvedPath + asset.Substring(packageInfo.assetPath.Length)); + }) + .ToArray(); + } + + public static string GetAssetFullPath(string asset) + { + var basePath = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); + return Path.GetFullPath(Path.Combine(basePath, Normalize(asset))); + } + + public static string Normalize(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + if (Path.DirectorySeparatorChar == WinSeparator) + path = path.Replace(UnixSeparator, WinSeparator); + + return path.Replace(string.Concat(WinSeparator, WinSeparator), WinSeparator.ToString()); + } + + internal static bool IsFileInProjectDirectory(string fileName) + { + var basePath = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); + fileName = Normalize(fileName); + + if (!Path.IsPathRooted(fileName)) + fileName = Path.Combine(basePath, fileName); + + return string.Equals(Path.GetDirectoryName(fileName), basePath, StringComparison.OrdinalIgnoreCase); + } + + public static string FileNameWithoutExtension(string path) + { + if (string.IsNullOrEmpty(path)) + { + return ""; + } + + var indexOfDot = -1; + var indexOfSlash = 0; + for (var i = path.Length - 1; i >= 0; i--) + { + if (indexOfDot == -1 && path[i] == '.') + { + indexOfDot = i; + } + + if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\') + { + indexOfSlash = i + 1; + break; + } + } + + if (indexOfDot == -1) + { + indexOfDot = path.Length - 1; + } + + return path.Substring(indexOfSlash, indexOfDot - indexOfSlash); + } + } +} diff --git a/Editor/Utility.cs.meta b/Editor/FileUtility.cs.meta similarity index 95% rename from Editor/Utility.cs.meta rename to Editor/FileUtility.cs.meta index 7cc03e7..f14ab79 100644 --- a/Editor/Utility.cs.meta +++ b/Editor/FileUtility.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 6f1dc05fb6e7d3e4f89ae9ca482735be -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 6f1dc05fb6e7d3e4f89ae9ca482735be +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature.meta b/Editor/Messaging.meta similarity index 73% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature.meta rename to Editor/Messaging.meta index 10f6d91..6c8374a 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature.meta +++ b/Editor/Messaging.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 55aae143147983c4ca41af0f79695248 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 2f820130c86c28547a0f1a2f4c73155b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/Deserializer.cs b/Editor/Messaging/Deserializer.cs new file mode 100644 index 0000000..039dc8f --- /dev/null +++ b/Editor/Messaging/Deserializer.cs @@ -0,0 +1,40 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System.IO; +using System.Text; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class Deserializer + { + private readonly BinaryReader _reader; + + // Max UDP packet size is 65507 + private const int MaxStringLength = 65000; + + public Deserializer(byte[] buffer) + { + _reader = new BinaryReader(new MemoryStream(buffer)); + } + + public int ReadInt32() + { + return _reader.ReadInt32(); + } + + public string ReadString() + { + var length = ReadInt32(); + return length > 0 && length <= MaxStringLength + ? Encoding.UTF8.GetString(_reader.ReadBytes(length)) + : ""; + } + + public bool CanReadMore() + { + return _reader.BaseStream.Position < _reader.BaseStream.Length; + } + } +} diff --git a/Editor/VSInitializer.cs.meta b/Editor/Messaging/Deserializer.cs.meta similarity index 80% rename from Editor/VSInitializer.cs.meta rename to Editor/Messaging/Deserializer.cs.meta index 508631f..9fc116b 100644 --- a/Editor/VSInitializer.cs.meta +++ b/Editor/Messaging/Deserializer.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: c70a64eb158b0104bb528b12e1d80c2a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 3eda7a83649158546826efb3ffe6c1e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/ExceptionEventArgs.cs b/Editor/Messaging/ExceptionEventArgs.cs new file mode 100644 index 0000000..617c71f --- /dev/null +++ b/Editor/Messaging/ExceptionEventArgs.cs @@ -0,0 +1,18 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class ExceptionEventArgs + { + public Exception Exception { get; } + + public ExceptionEventArgs(Exception exception) + { + Exception = exception; + } + } +} diff --git a/Editor/Messaging/ExceptionEventArgs.cs.meta b/Editor/Messaging/ExceptionEventArgs.cs.meta new file mode 100644 index 0000000..f53f8a3 --- /dev/null +++ b/Editor/Messaging/ExceptionEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 917a51fff055ce547b4ad1215321f3da +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/Message.cs b/Editor/Messaging/Message.cs new file mode 100644 index 0000000..77eae14 --- /dev/null +++ b/Editor/Messaging/Message.cs @@ -0,0 +1,23 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System.Globalization; +using System.Net; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class Message + { + public MessageType Type { get; set; } + + public string Value { get; set; } + + public IPEndPoint Origin { get; set; } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "", Type, Value); + } + } +} diff --git a/Editor/Messaging/Message.cs.meta b/Editor/Messaging/Message.cs.meta new file mode 100644 index 0000000..2163640 --- /dev/null +++ b/Editor/Messaging/Message.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: de1c9ea7b82c9904d9e5fba2ee70a998 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/MessageEventArgs.cs b/Editor/Messaging/MessageEventArgs.cs new file mode 100644 index 0000000..10ffb93 --- /dev/null +++ b/Editor/Messaging/MessageEventArgs.cs @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class MessageEventArgs + { + public Message Message + { + get; + } + + public MessageEventArgs(Message message) + { + Message = message; + } + } +} diff --git a/Editor/Messaging/MessageEventArgs.cs.meta b/Editor/Messaging/MessageEventArgs.cs.meta new file mode 100644 index 0000000..e09b3e4 --- /dev/null +++ b/Editor/Messaging/MessageEventArgs.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 275143c81d816ef4286fdc67aabc20c8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/MessageType.cs b/Editor/Messaging/MessageType.cs new file mode 100644 index 0000000..9850e68 --- /dev/null +++ b/Editor/Messaging/MessageType.cs @@ -0,0 +1,34 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal enum MessageType + { + None = 0, + + Ping, + Pong, + + Play, + Stop, + Pause, + Unpause, + + Build, + Refresh, + + Info, + Error, + Warning, + + Open, + Opened, + + Version, + UpdatePackage, + + ProjectPath, + } +} diff --git a/Editor/Messaging/MessageType.cs.meta b/Editor/Messaging/MessageType.cs.meta new file mode 100644 index 0000000..ae0d328 --- /dev/null +++ b/Editor/Messaging/MessageType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3edbdc86577af648a23263aa75161e1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/Messenger.cs b/Editor/Messaging/Messenger.cs new file mode 100644 index 0000000..49ae086 --- /dev/null +++ b/Editor/Messaging/Messenger.cs @@ -0,0 +1,176 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Net; +using System.Net.Sockets; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class Messager : IDisposable + { + public event EventHandler ReceiveMessage; + public event EventHandler MessagerException; + + private readonly UdpSocket _socket; + private readonly object _disposeLock = new object(); + private bool _disposed; + + protected Messager(int port) + { + _socket = new UdpSocket(); + _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, false); + _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + _socket.Bind(IPAddress.Any, port); + + BeginReceiveMessage(); + } + + private void BeginReceiveMessage() + { + var buffer = new byte[UdpSocket.BufferSize]; + var any = UdpSocket.Any(); + + try + { + lock (_disposeLock) + { + if (_disposed) + return; + + _socket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref any, ReceiveMessageCallback, buffer); + } + } + catch (SocketException se) + { + MessagerException?.Invoke(this, new ExceptionEventArgs(se)); + + BeginReceiveMessage(); + } + catch (ObjectDisposedException) + { + } + } + + private void ReceiveMessageCallback(IAsyncResult result) + { + try + { + var endPoint = UdpSocket.Any(); + + lock (_disposeLock) + { + if (_disposed) + return; + + _socket.EndReceiveFrom(result, ref endPoint); + } + + var message = DeserializeMessage(UdpSocket.BufferFor(result)); + if (message != null) + { + message.Origin = (IPEndPoint)endPoint; + ReceiveMessage?.Invoke(this, new MessageEventArgs(message)); + } + } + catch (ObjectDisposedException) + { + return; + } + catch (Exception e) + { + RaiseMessagerException(e); + } + + BeginReceiveMessage(); + } + + private void RaiseMessagerException(Exception e) + { + MessagerException?.Invoke(this, new ExceptionEventArgs(e)); + } + + private static Message MessageFor(MessageType type, string value) + { + return new Message { Type = type, Value = value }; + } + + public void SendMessage(IPEndPoint target, MessageType type, string value = "") + { + var message = MessageFor(type, value); + var buffer = SerializeMessage(message); + + try + { + lock (_disposeLock) + { + if (_disposed) + return; + + _socket.BeginSendTo(buffer, 0, Math.Min(buffer.Length, UdpSocket.BufferSize), SocketFlags.None, target, SendMessageCallback, null); + } + } + catch (SocketException se) + { + MessagerException?.Invoke(this, new ExceptionEventArgs(se)); + } + } + + private void SendMessageCallback(IAsyncResult result) + { + try + { + lock (_disposeLock) + { + if (_disposed) + return; + + _socket.EndSendTo(result); + } + } + catch (SocketException se) + { + MessagerException?.Invoke(this, new ExceptionEventArgs(se)); + } + catch (ObjectDisposedException) + { + } + } + + private static byte[] SerializeMessage(Message message) + { + var serializer = new Serializer(); + serializer.WriteInt32((int)message.Type); + serializer.WriteString(message.Value); + + return serializer.Buffer(); + } + + private static Message DeserializeMessage(byte[] buffer) + { + if (buffer.Length < 4) + return null; + + var deserializer = new Deserializer(buffer); + var type = (MessageType)deserializer.ReadInt32(); + var value = deserializer.ReadString(); + + return new Message { Type = type, Value = value }; + } + + public static Messager BindTo(int port) + { + return new Messager(port); + } + + public void Dispose() + { + lock (_disposeLock) + { + _disposed = true; + _socket.Close(); + } + } + } +} diff --git a/Editor/Messaging/Messenger.cs.meta b/Editor/Messaging/Messenger.cs.meta new file mode 100644 index 0000000..89d8421 --- /dev/null +++ b/Editor/Messaging/Messenger.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5e249ae353801f043a6e4173410c6152 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/Serializer.cs b/Editor/Messaging/Serializer.cs new file mode 100644 index 0000000..6324318 --- /dev/null +++ b/Editor/Messaging/Serializer.cs @@ -0,0 +1,43 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System.IO; +using System.Text; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class Serializer + { + private readonly MemoryStream _stream; + private readonly BinaryWriter _writer; + + public Serializer() + { + _stream = new MemoryStream(); + _writer = new BinaryWriter(_stream); + } + + public void WriteInt32(int i) + { + _writer.Write(i); + } + + public void WriteString(string s) + { + var bytes = Encoding.UTF8.GetBytes(s ?? ""); + if (bytes.Length > 0) + { + _writer.Write(bytes.Length); + _writer.Write(bytes); + } + else + _writer.Write(0); + } + + public byte[] Buffer() + { + return _stream.ToArray(); + } + } +} diff --git a/Editor/Messaging/Serializer.cs.meta b/Editor/Messaging/Serializer.cs.meta new file mode 100644 index 0000000..e664c14 --- /dev/null +++ b/Editor/Messaging/Serializer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 369c09afe05d2c346af49faef943c773 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Messaging/UdpSocket.cs b/Editor/Messaging/UdpSocket.cs new file mode 100644 index 0000000..2432dba --- /dev/null +++ b/Editor/Messaging/UdpSocket.cs @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Net; +using System.Net.Sockets; + +namespace Microsoft.Unity.VisualStudio.Editor.Messaging +{ + internal class UdpSocket : Socket + { + public const int BufferSize = 1024 * 8; + + internal UdpSocket() + : base(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) + { + SetIOControl(); + } + + public void Bind(IPAddress address, int port = 0) + { + Bind(new IPEndPoint(address ?? IPAddress.Any, port)); + } + + private void SetIOControl() + { + if (!VisualStudioEditor.IsWindows) + return; + + try + { + const int SIO_UDP_CONNRESET = -1744830452; + + IOControl(SIO_UDP_CONNRESET, new byte[] { 0 }, new byte[0]); + } + catch + { + // fallback + } + } + + public static byte[] BufferFor(IAsyncResult result) + { + return (byte[])result.AsyncState; + } + + public static EndPoint Any() + { + return new IPEndPoint(IPAddress.Any, 0); + } + } +} diff --git a/Editor/Messaging/UdpSocket.cs.meta b/Editor/Messaging/UdpSocket.cs.meta new file mode 100644 index 0000000..8852c5a --- /dev/null +++ b/Editor/Messaging/UdpSocket.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38cb3a4a17d2cfd41926da95ce675934 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins.meta b/Editor/Plugins.meta index 6e01768..676fbb1 100644 --- a/Editor/Plugins.meta +++ b/Editor/Plugins.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 1e5abb64fdd0542b38f4dc1b60343e8a -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 1e5abb64fdd0542b38f4dc1b60343e8a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta b/Editor/Plugins/AppleEventIntegration.bundle.meta similarity index 88% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta rename to Editor/Plugins/AppleEventIntegration.bundle.meta index 991b7e7..e5b6825 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta +++ b/Editor/Plugins/AppleEventIntegration.bundle.meta @@ -1,28 +1,28 @@ -fileFormatVersion: 2 -guid: dd66e4390e06fc14e92b9822744f2fb1 -folderAsset: yes -PluginImporter: - externalObjects: {} - serializedVersion: 2 - iconMap: {} - executionOrder: {} - defineConstraints: [] - isPreloaded: 0 - isOverridable: 1 - isExplicitlyReferenced: 0 - validateReferences: 1 - platformData: - - first: - Any: - second: - enabled: 0 - settings: {} - - first: - Editor: Editor - second: - enabled: 1 - settings: - DefaultValueInitialized: true - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: a20df6e3467b24ed5b49c857ce39e096 +folderAsset: yes +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta b/Editor/Plugins/AppleEventIntegration.bundle/Contents.meta similarity index 73% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta rename to Editor/Plugins/AppleEventIntegration.bundle/Contents.meta index 1eeb0e2..03a3bfb 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta +++ b/Editor/Plugins/AppleEventIntegration.bundle/Contents.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 179209ff257e808409c755d32ecf1086 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 058b02c03ea09473aab4dc5fc50af1ef +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist b/Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist similarity index 76% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist rename to Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist index 50c0c33..3b52961 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist +++ b/Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist @@ -1,44 +1,42 @@ - - - - - BuildMachineOSBuild - 18E226 - CFBundleDevelopmentRegion - en - CFBundleExecutable - AppleEventIntegrationPlugin - CFBundleIdentifier - com.unity.AppleEventIntegrationPlugin - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - AppleEventIntegrationPlugin - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSupportedPlatforms - - MacOSX - - CFBundleVersion - 1 - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 10E1001 - DTPlatformVersion - GM - DTSDKBuild - 18E219 - DTSDKName - macosx10.14 - DTXcode - 1020 - DTXcodeBuild - 10E1001 - NSHumanReadableCopyright - Copyright © 2019 Unity. All rights reserved. - - + + + + + BuildMachineOSBuild + 19B88 + CFBundleDevelopmentRegion + en + CFBundleExecutable + AppleEventIntegration + CFBundleIdentifier + com.unity.visualstudio.AppleEventIntegration + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + AppleEventIntegration + CFBundleShortVersionString + 1.0 + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 10E125 + DTPlatformVersion + GM + DTSDKBuild + 18E219 + DTSDKName + macosx10.14 + DTXcode + 1020 + DTXcodeBuild + 10E125 + NSHumanReadableCopyright + Copyright © 2019 Unity. All rights reserved. + + diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta b/Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist.meta similarity index 71% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta rename to Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist.meta index 4d47fc5..1f49dac 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta +++ b/Editor/Plugins/AppleEventIntegration.bundle/Contents/Info.plist.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: d2694cce95579ec47a939a1a3efb8f33 -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 680cf1008b4284eddbb82ec4d76644a1 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta b/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS.meta similarity index 73% rename from Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta rename to Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS.meta index 773ad15..8c69d7f 100644 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta +++ b/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: a0f0c231a0e381e4ea37a97a8e7837a0 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: ba4355216f6c44abbb17503872c42c97 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration b/Editor/Plugins/AppleEventIntegration.bundle/Contents/MacOS/AppleEventIntegration new file mode 100644 index 0000000000000000000000000000000000000000..bf56250f6f8076a7d47f208584335ee5dd76ee92 GIT binary patch literal 19980 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 - - - - files - - files2 - - rules - - ^Resources/ - - ^Resources/.*\.lproj/ - - optional - - weight - 1000 - - ^Resources/.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Resources/Base\.lproj/ - - weight - 1010 - - ^version.plist$ - - - rules2 - - .*\.dSYM($|/) - - weight - 11 - - ^(.*/)?\.DS_Store$ - - omit - - weight - 2000 - - ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ - - nested - - weight - 10 - - ^.* - - ^Info\.plist$ - - omit - - weight - 20 - - ^PkgInfo$ - - omit - - weight - 20 - - ^Resources/ - - weight - 20 - - ^Resources/.*\.lproj/ - - optional - - weight - 1000 - - ^Resources/.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Resources/Base\.lproj/ - - weight - 1010 - - ^[^/]+$ - - nested - - weight - 10 - - ^embedded\.provisionprofile$ - - weight - 20 - - ^version\.plist$ - - weight - 20 - - - - diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta deleted file mode 100644 index 7968517..0000000 --- a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 8529f5a60acb8cd4395bd1cec74495ae -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Editor/ProjectGeneration.cs b/Editor/ProjectGeneration.cs index e50aadc..5ffc9e0 100644 --- a/Editor/ProjectGeneration.cs +++ b/Editor/ProjectGeneration.cs @@ -1,890 +1,1028 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security; -using System.Security.Cryptography; -using System.Text; -using System.Text.RegularExpressions; -using System.Xml; -using UnityEditor; -using UnityEditor.Compilation; -using UnityEditor.PackageManager; -using UnityEditor.Scripting.Compilers; -using UnityEditorInternal; -using UnityEngine; - -namespace VisualStudioEditor -{ - public interface IGenerator { - bool SyncIfNeeded(IEnumerable affectedFiles, IEnumerable reimportedFiles); - void Sync(); - bool HasSolutionBeenGenerated(); - string SolutionFile(); - string ProjectDirectory { get; } - void GenerateAll(bool generateAll); - } - - public interface IAssemblyNameProvider - { - string GetAssemblyNameFromScriptPath(string path); - IEnumerable GetAllAssemblies(Func shouldFileBePartOfSolution); - IEnumerable GetAllAssetPaths(); - UnityEditor.PackageManager.PackageInfo FindForAssetPath(string assetPath); - } - - public struct TestSettings { - public bool ShouldSync; - public Dictionary SyncPath; - } - - class AssemblyNameProvider : IAssemblyNameProvider - { - public string GetAssemblyNameFromScriptPath(string path) - { - return CompilationPipeline.GetAssemblyNameFromScriptPath(path); - } - - public IEnumerable GetAllAssemblies(Func shouldFileBePartOfSolution) - { - return CompilationPipeline.GetAssemblies().Where(i => 0 < i.sourceFiles.Length && i.sourceFiles.Any(shouldFileBePartOfSolution)); - } - - public IEnumerable GetAllAssetPaths() - { - return AssetDatabase.GetAllAssetPaths(); - } - - public UnityEditor.PackageManager.PackageInfo FindForAssetPath(string assetPath) - { - return UnityEditor.PackageManager.PackageInfo.FindForAssetPath(assetPath); - } - } - - public class ProjectGeneration : IGenerator - { - enum ScriptingLanguage - { - None, - CSharp - } - - public static readonly string MSBuildNamespaceUri = "http://schemas.microsoft.com/developer/msbuild/2003"; - - const string k_WindowsNewline = "\r\n"; - - /// - /// Map source extensions to ScriptingLanguages - /// - static readonly Dictionary k_BuiltinSupportedExtensions = new Dictionary - { - { "cs", ScriptingLanguage.CSharp }, - { "uxml", ScriptingLanguage.None }, - { "uss", ScriptingLanguage.None }, - { "shader", ScriptingLanguage.None }, - { "compute", ScriptingLanguage.None }, - { "cginc", ScriptingLanguage.None }, - { "hlsl", ScriptingLanguage.None }, - { "glslinc", ScriptingLanguage.None } - }; - - string m_SolutionProjectEntryTemplate = string.Join("\r\n", - @"Project(""{{{0}}}"") = ""{1}"", ""{2}"", ""{{{3}}}""", - @"EndProject").Replace(" ", "\t"); - - string m_SolutionProjectConfigurationTemplate = string.Join("\r\n", - @" {{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", - @" {{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", - @" {{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", - @" {{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU").Replace(" ", "\t"); - - static readonly string[] k_ReimportSyncExtensions = { ".dll", ".asmdef" }; - - static readonly Regex k_ScriptReferenceExpression = new Regex( - @"^Library.ScriptAssemblies.(?(?.*)\.dll$)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); - - string[] m_ProjectSupportedExtensions = new string[0]; - public string ProjectDirectory { get; } - - public TestSettings Settings { get; set; } - - readonly string m_ProjectName; - readonly IAssemblyNameProvider m_AssemblyNameProvider; - bool m_ShouldGenerateAll; - - public ProjectGeneration() : this(Directory.GetParent(Application.dataPath).FullName, new AssemblyNameProvider()) - { - } - - public ProjectGeneration(string tempDirectory) : this(tempDirectory, new AssemblyNameProvider()) { - } - - public ProjectGeneration(string tempDirectory, IAssemblyNameProvider assemblyNameProvider) { - Settings = new TestSettings { ShouldSync = true }; - ProjectDirectory = tempDirectory.Replace('\\', '/'); - m_ProjectName = Path.GetFileName(ProjectDirectory); - m_AssemblyNameProvider = assemblyNameProvider; - } - - public void GenerateAll(bool generateAll) - { - m_ShouldGenerateAll = generateAll; - } - - /// - /// Syncs the scripting solution if any affected files are relevant. - /// - /// - /// Whether the solution was synced. - /// - /// - /// A set of files whose status has changed - /// - /// - /// A set of files that got reimported - /// - public bool SyncIfNeeded(IEnumerable affectedFiles, IEnumerable reimportedFiles) - { - SetupProjectSupportedExtensions(); - - // Don't sync if we haven't synced before - if (HasSolutionBeenGenerated() && HasFilesBeenModified(affectedFiles, reimportedFiles)) - { - Sync(); - return true; - } - return false; - } - - bool HasFilesBeenModified(IEnumerable affectedFiles, IEnumerable reimportedFiles) - { - return affectedFiles.Any(ShouldFileBePartOfSolution) || reimportedFiles.Any(ShouldSyncOnReimportedAsset); - } - - static bool ShouldSyncOnReimportedAsset(string asset) - { - return k_ReimportSyncExtensions.Contains(new FileInfo(asset).Extension); - } - - public void Sync() - { - SetupProjectSupportedExtensions(); - bool externalCodeAlreadyGeneratedProjects = OnPreGeneratingCSProjectFiles(); - - if (!externalCodeAlreadyGeneratedProjects) - { - GenerateAndWriteSolutionAndProjects(); - } - OnGeneratedCSProjectFiles(); - } - - public bool HasSolutionBeenGenerated() - { - return File.Exists(SolutionFile()); - } - - void SetupProjectSupportedExtensions() - { - m_ProjectSupportedExtensions = EditorSettings.projectGenerationUserExtensions; - } - - bool ShouldFileBePartOfSolution(string file) - { - string extension = Path.GetExtension(file); - - // Exclude files coming from packages except if they are internalized. - if (!m_ShouldGenerateAll && IsInternalizedPackagePath(file)) - { - return false; - } - - // Dll's are not scripts but still need to be included.. - if (extension == ".dll") - return true; - - if (file.ToLower().EndsWith(".asmdef")) - return true; - - return IsSupportedExtension(extension); - } - - bool IsSupportedExtension(string extension) - { - extension = extension.TrimStart('.'); - if (k_BuiltinSupportedExtensions.ContainsKey(extension)) - return true; - if (m_ProjectSupportedExtensions.Contains(extension)) - return true; - return false; - } - - static ScriptingLanguage ScriptingLanguageFor(Assembly island) - { - return ScriptingLanguageFor(GetExtensionOfSourceFiles(island.sourceFiles)); - } - - static string GetExtensionOfSourceFiles(string[] files) - { - return files.Length > 0 ? GetExtensionOfSourceFile(files[0]) : "NA"; - } - - static string GetExtensionOfSourceFile(string file) - { - var ext = Path.GetExtension(file).ToLower(); - ext = ext.Substring(1); //strip dot - return ext; - } - - static ScriptingLanguage ScriptingLanguageFor(string extension) - { - return k_BuiltinSupportedExtensions.TryGetValue(extension.TrimStart('.'), out var result) - ? result - : ScriptingLanguage.None; - } - - static List SafeGetTypes(System.Reflection.Assembly a) - { - var ret = new List(); - - try - { - ret = a.GetTypes().ToList(); - } - catch (System.Reflection.ReflectionTypeLoadException rtl) - { - ret = rtl.Types.ToList(); - } - catch (Exception) - { - return new List(); - } - - return ret.Where(r => r != null).ToList(); - } - - public void GenerateAndWriteSolutionAndProjects() - { - // Only synchronize islands that have associated source files and ones that we actually want in the project. - // This also filters out DLLs coming from .asmdef files in packages. - var assemblies = m_AssemblyNameProvider.GetAllAssemblies(ShouldFileBePartOfSolution); - - var allAssetProjectParts = GenerateAllAssetProjectParts(); - - var monoIslands = assemblies.ToList(); - - SyncSolution(monoIslands); - var allProjectIslands = RelevantIslandsForMode(monoIslands).ToList(); - foreach (Assembly assembly in allProjectIslands) - { - var responseFileData = ParseResponseFileData(assembly); - SyncProject(assembly, allAssetProjectParts, responseFileData, allProjectIslands); - } - } - - IEnumerable ParseResponseFileData(Assembly assembly) - { - var systemReferenceDirectories = CompilationPipeline.GetSystemAssemblyDirectories(assembly.compilerOptions.ApiCompatibilityLevel); - - Dictionary responseFilesData = assembly.compilerOptions.ResponseFiles.ToDictionary(x => x, x => CompilationPipeline.ParseResponseFile( - Path.Combine(ProjectDirectory, x), - ProjectDirectory, - systemReferenceDirectories - )); - - Dictionary responseFilesWithErrors = responseFilesData.Where(x => x.Value.Errors.Any()) - .ToDictionary(x => x.Key, x => x.Value); - - if (responseFilesWithErrors.Any()) - { - foreach (var error in responseFilesWithErrors) - foreach (var valueError in error.Value.Errors) - { - Debug.LogError($"{error.Key} Parse Error : {valueError}"); - } - } - - return responseFilesData.Select(x => x.Value); - } - - Dictionary GenerateAllAssetProjectParts() - { - Dictionary stringBuilders = new Dictionary(); - - foreach (string asset in m_AssemblyNameProvider.GetAllAssetPaths()) - { - // Exclude files coming from packages except if they are internalized. - if (!m_ShouldGenerateAll && IsInternalizedPackagePath(asset)) - { - continue; - } - - string extension = Path.GetExtension(asset); - if (IsSupportedExtension(extension) && ScriptingLanguage.None == ScriptingLanguageFor(extension)) - { - // Find assembly the asset belongs to by adding script extension and using compilation pipeline. - var assemblyName = m_AssemblyNameProvider.GetAssemblyNameFromScriptPath(asset + ".cs"); - - if (string.IsNullOrEmpty(assemblyName)) - { - continue; - } - - assemblyName = Utility.FileNameWithoutExtension(assemblyName); - - if (!stringBuilders.TryGetValue(assemblyName, out var projectBuilder)) - { - projectBuilder = new StringBuilder(); - stringBuilders[assemblyName] = projectBuilder; - } - - projectBuilder.Append(" ").Append(k_WindowsNewline); - } - } - - var result = new Dictionary(); - - foreach (var entry in stringBuilders) - result[entry.Key] = entry.Value.ToString(); - - return result; - } - - bool IsInternalizedPackagePath(string file) - { - if (string.IsNullOrWhiteSpace(file)) - { - return false; - } - - var packageInfo = m_AssemblyNameProvider.FindForAssetPath(file); - if (packageInfo == null) { - return false; - } - var packageSource = packageInfo.source; - return packageSource != PackageSource.Embedded && packageSource != PackageSource.Local; - } - - void SyncProject( - Assembly island, - Dictionary allAssetsProjectParts, - IEnumerable responseFilesData, - List allProjectIslands) - { - SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, allAssetsProjectParts, responseFilesData, allProjectIslands)); - } - - void SyncProjectFileIfNotChanged(string path, string newContents) - { - if (Path.GetExtension(path) == ".csproj") - { - newContents = OnGeneratedCSProject(path, newContents); - } - - SyncFileIfNotChanged(path, newContents); - } - - void SyncSolutionFileIfNotChanged(string path, string newContents) - { - newContents = OnGeneratedSlnSolution(path, newContents); - - SyncFileIfNotChanged(path, newContents); - } - - static void OnGeneratedCSProjectFiles() - { - IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) - .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); - var args = new object[0]; - foreach (var type in types) - { - var method = type.GetMethod("OnGeneratedCSProjectFiles", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); - if (method == null) - { - continue; - } - method.Invoke(null, args); - } - } - - static bool OnPreGeneratingCSProjectFiles() - { - IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) - .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); - bool result = false; - foreach (var type in types) - { - var args = new object[0]; - var method = type.GetMethod("OnPreGeneratingCSProjectFiles", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); - if (method == null) - { - continue; - } - var returnValue = method.Invoke(null, args); - if (method.ReturnType == typeof(bool)) - { - result |= (bool)returnValue; - } - } - return result; - } - - static string OnGeneratedCSProject(string path, string content) - { - IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) - .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); - foreach (var type in types) - { - var args = new [] { path, content }; - var method = type.GetMethod("OnGeneratedCSProject", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); - if (method == null) - { - continue; - } - var returnValue = method.Invoke(null, args); - if (method.ReturnType == typeof(string)) - { - content = (string)returnValue; - } - } - return content; - } - - static string OnGeneratedSlnSolution(string path, string content) - { - IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) - .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); - foreach (var type in types) - { - var args = new [] { path, content }; - var method = type.GetMethod("OnGeneratedSlnSolution", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); - if (method == null) - { - continue; - } - var returnValue = method.Invoke(null, args); - if (method.ReturnType == typeof(string)) - { - content = (string)returnValue; - } - } - return content; - } - - void SyncFileIfNotChanged(string filename, string newContents) - { - if (File.Exists(filename) && - newContents == File.ReadAllText(filename)) - { - return; - } - - if (Settings.ShouldSync) - { - File.WriteAllText(filename, newContents, Encoding.UTF8); - } - else - { - var utf8 = Encoding.UTF8; - byte[] utfBytes = utf8.GetBytes(newContents); - Settings.SyncPath[filename] = utf8.GetString(utfBytes, 0, utfBytes.Length); - } - } - - string ProjectText(Assembly assembly, - Dictionary allAssetsProjectParts, - IEnumerable responseFilesData, - List allProjectIslands) - { - var projectBuilder = new StringBuilder(ProjectHeader(assembly, responseFilesData)); - var references = new List(); - var projectReferences = new List(); - - foreach (string file in assembly.sourceFiles) - { - if (!ShouldFileBePartOfSolution(file)) - continue; - - var extension = Path.GetExtension(file).ToLower(); - var fullFile = EscapedRelativePathFor(file); - if (".dll" != extension) - { - projectBuilder.Append(" ").Append(k_WindowsNewline); - } - else - { - references.Add(fullFile); - } - } - - var assemblyName = Utility.FileNameWithoutExtension(assembly.outputPath); - - // Append additional non-script files that should be included in project generation. - if (allAssetsProjectParts.TryGetValue(assemblyName, out var additionalAssetsForProject)) - projectBuilder.Append(additionalAssetsForProject); - - var islandRefs = references.Union(assembly.allReferences); - - foreach (string reference in islandRefs) - { - if (reference.EndsWith("/UnityEditor.dll", StringComparison.Ordinal) - || reference.EndsWith("/UnityEngine.dll", StringComparison.Ordinal) - || reference.EndsWith("\\UnityEditor.dll", StringComparison.Ordinal) - || reference.EndsWith("\\UnityEngine.dll", StringComparison.Ordinal)) - continue; - - var match = k_ScriptReferenceExpression.Match(reference); - if (match.Success) - { - // assume csharp language - // Add a reference to a project except if it's a reference to a script assembly - // that we are not generating a project for. This will be the case for assemblies - // coming from .assembly.json files in non-internalized packages. - var dllName = match.Groups["dllname"].Value; - if (allProjectIslands.Any(i => Path.GetFileName(i.outputPath) == dllName)) - { - projectReferences.Add(match); - continue; - } - } - - string fullReference = Path.IsPathRooted(reference) ? reference : Path.Combine(ProjectDirectory, reference); - - AppendReference(fullReference, projectBuilder); - } - - var responseRefs = responseFilesData.SelectMany(x => x.FullPathReferences.Select(r => r)); - foreach (var reference in responseRefs) - { - AppendReference(reference, projectBuilder); - } - - if (0 < projectReferences.Count) - { - projectBuilder.AppendLine(" "); - projectBuilder.AppendLine(" "); - foreach (Match reference in projectReferences) - { - var referencedProject = reference.Groups["project"].Value; - - projectBuilder.Append(" ").Append(k_WindowsNewline); - projectBuilder.Append(" {").Append(ProjectGuid(Path.Combine("Temp", reference.Groups["project"].Value + ".dll"))).Append("}").Append(k_WindowsNewline); - projectBuilder.Append(" ").Append(referencedProject).Append("").Append(k_WindowsNewline); - projectBuilder.AppendLine(" "); - } - } - - projectBuilder.Append(ProjectFooter()); - return projectBuilder.ToString(); - } - - static void AppendReference(string fullReference, StringBuilder projectBuilder) - { - //replace \ with / and \\ with / - var escapedFullPath = SecurityElement.Escape(fullReference); - escapedFullPath = escapedFullPath.Replace("\\", "/"); - escapedFullPath = escapedFullPath.Replace("\\\\", "/"); - projectBuilder.Append(" ").Append(k_WindowsNewline); - projectBuilder.Append(" ").Append(escapedFullPath).Append("").Append(k_WindowsNewline); - projectBuilder.Append(" ").Append(k_WindowsNewline); - } - - public string ProjectFile(Assembly assembly) - { - return Path.Combine(ProjectDirectory, $"{Utility.FileNameWithoutExtension(assembly.outputPath)}.csproj"); - } - - public string SolutionFile() - { - return Path.Combine(ProjectDirectory, $"{m_ProjectName}.sln"); - } - - string ProjectHeader( - Assembly island, - IEnumerable responseFilesData - ) - { - var toolsVersion = "4.0"; - var productVersion = "10.0.20506"; - const string baseDirectory = "."; - - var targetFrameworkVersion = "v4.7.1"; - var targetLanguageVersion = "latest"; - - var arguments = new object[] - { - toolsVersion, productVersion, ProjectGuid(island.outputPath), - InternalEditorUtility.GetEngineAssemblyPath(), - InternalEditorUtility.GetEditorAssemblyPath(), - string.Join(";", new[] { "DEBUG", "TRACE" }.Concat(EditorUserBuildSettings.activeScriptCompilationDefines).Concat(island.defines).Concat(responseFilesData.SelectMany(x => x.Defines)).Distinct().ToArray()), - MSBuildNamespaceUri, - Utility.FileNameWithoutExtension(island.outputPath), - EditorSettings.projectGenerationRootNamespace, - targetFrameworkVersion, - targetLanguageVersion, - baseDirectory, - island.compilerOptions.AllowUnsafeCode | responseFilesData.Any(x => x.Unsafe) - }; - - try - { - return string.Format(GetProjectHeaderTemplate(), arguments); - } - catch (Exception) - { - throw new NotSupportedException("Failed creating c# project because the c# project header did not have the correct amount of arguments, which is " + arguments.Length); - } - } - - static string GetSolutionText() - { - return string.Join("\r\n", - @"", - @"Microsoft Visual Studio Solution File, Format Version {0}", - @"# Visual Studio {1}", - @"{2}", - @"Global", - @" GlobalSection(SolutionConfigurationPlatforms) = preSolution", - @" Debug|Any CPU = Debug|Any CPU", - @" Release|Any CPU = Release|Any CPU", - @" EndGlobalSection", - @" GlobalSection(ProjectConfigurationPlatforms) = postSolution", - @"{3}", - @" EndGlobalSection", - @" GlobalSection(SolutionProperties) = preSolution", - @" HideSolutionNode = FALSE", - @" EndGlobalSection", - @"EndGlobal", - @"").Replace(" ", "\t"); - } - - static string GetProjectFooterTemplate() - { - return string.Join("\r\n", - @" ", - @" ", - @" ", - @"", - @""); - } - - static string GetProjectHeaderTemplate() - { - var header = new[] - { - @"", - @"", - @" ", - @" {10}", - @" ", - @" ", - @" Debug", - @" AnyCPU", - @" {1}", - @" 2.0", - @" {8}", - @" {{{2}}}", - @" Library", - @" Properties", - @" {7}", - @" {9}", - @" 512", - @" {11}", - @" ", - @" ", - @" true", - @" full", - @" false", - @" Temp\bin\Debug\", - @" {5}", - @" prompt", - @" 4", - @" 0169", - @" {12}", - @" ", - @" ", - @" pdbonly", - @" true", - @" Temp\bin\Release\", - @" prompt", - @" 4", - @" 0169", - @" {12}", - @" " - }; - - var forceExplicitReferences = new[] - { - @" ", - @" true", - @" true", - @" false", - @" false", - @" false", - @" " - }; - - var itemGroupStart = new[] - { - @" " - }; - - var footer = new[] - { - @" ", - @" {3}", - @" ", - @" ", - @" {4}", - @" ", - @" ", - @" ", - @"" - }; - - var text = header.Concat(forceExplicitReferences).Concat(itemGroupStart).Concat(footer).ToArray(); - return string.Join("\r\n", text); - } - - void SyncSolution(IEnumerable islands) - { - SyncSolutionFileIfNotChanged(SolutionFile(), SolutionText(islands)); - } - - string SolutionText(IEnumerable islands) - { - var fileversion = "11.00"; - var vsversion = "2010"; - - var relevantIslands = RelevantIslandsForMode(islands); - string projectEntries = GetProjectEntries(relevantIslands); - string projectConfigurations = string.Join(k_WindowsNewline, relevantIslands.Select(i => GetProjectActiveConfigurations(ProjectGuid(i.outputPath))).ToArray()); - return string.Format(GetSolutionText(), fileversion, vsversion, projectEntries, projectConfigurations); - } - - static IEnumerable RelevantIslandsForMode(IEnumerable islands) - { - IEnumerable relevantIslands = islands.Where(i => ScriptingLanguage.CSharp == ScriptingLanguageFor(i)); - return relevantIslands; - } - - /// - /// Get a Project("{guid}") = "MyProject", "MyProject.unityproj", "{projectguid}" - /// entry for each relevant language - /// - string GetProjectEntries(IEnumerable islands) - { - var projectEntries = islands.Select(i => string.Format( - m_SolutionProjectEntryTemplate, - SolutionGuid(i), Utility.FileNameWithoutExtension(i.outputPath), Path.GetFileName(ProjectFile(i)), ProjectGuid(i.outputPath) - )); - - return string.Join(k_WindowsNewline, projectEntries.ToArray()); - } - - /// - /// Generate the active configuration string for a given project guid - /// - string GetProjectActiveConfigurations(string projectGuid) - { - return string.Format( - m_SolutionProjectConfigurationTemplate, - projectGuid); - } - - string EscapedRelativePathFor(string file) - { - var projectDir = ProjectDirectory.Replace('/', '\\'); - file = file.Replace('/', '\\'); - var path = SkipPathPrefix(file, projectDir); - - var packageInfo = m_AssemblyNameProvider.FindForAssetPath(path.Replace('\\', '/')); - if (packageInfo != null) { - // We have to normalize the path, because the PackageManagerRemapper assumes - // dir seperators will be os specific. - var absolutePath = Path.GetFullPath(NormalizePath(path)).Replace('/', '\\'); - path = SkipPathPrefix(absolutePath, projectDir); - } - - return SecurityElement.Escape(path); - } - - static string SkipPathPrefix(string path, string prefix) - { - if (path.Replace("\\","/").StartsWith($"{prefix}/")) - return path.Substring(prefix.Length + 1); - return path; - } - - static string NormalizePath(string path) - { - if (Path.DirectorySeparatorChar == '\\') - return path.Replace('/', Path.DirectorySeparatorChar); - return path.Replace('\\', Path.DirectorySeparatorChar); - } - - - string ProjectGuid(string assembly) - { - return SolutionGuidGenerator.GuidForProject(m_ProjectName + Utility.FileNameWithoutExtension(assembly)); - } - - string SolutionGuid(Assembly island) - { - return SolutionGuidGenerator.GuidForSolution(m_ProjectName, GetExtensionOfSourceFiles(island.sourceFiles)); - } - - static string ProjectFooter() - { - return GetProjectFooterTemplate(); - } - - static string GetProjectExtension() - { - return ".csproj"; - } - } - - public static class SolutionGuidGenerator - { - public static string GuidForProject(string projectName) - { - return ComputeGuidHashFor(projectName + "salt"); - } - - public static string GuidForSolution(string projectName, string sourceFileExtension) - { - if (sourceFileExtension.ToLower() == "cs") - // GUID for a C# class library: http://www.codeproject.com/Reference/720512/List-of-Visual-Studio-Project-Type-GUIDs - return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"; - - return ComputeGuidHashFor(projectName); - } - - static string ComputeGuidHashFor(string input) - { - var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(input)); - return HashAsGuid(HashToString(hash)); - } - - static string HashAsGuid(string hash) - { - var guid = hash.Substring(0, 8) + "-" + hash.Substring(8, 4) + "-" + hash.Substring(12, 4) + "-" + hash.Substring(16, 4) + "-" + hash.Substring(20, 12); - return guid.ToUpper(); - } - - static string HashToString(byte[] bs) - { - var sb = new StringBuilder(); - foreach (byte b in bs) - sb.Append(b.ToString("x2")); - return sb.ToString(); - } - } -} +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Unity Technologies. + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using Unity.CodeEditor; +using UnityEditor; +using UnityEditor.Compilation; +using UnityEditor.PackageManager; +using UnityEditorInternal; +using UnityEngine; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + public enum ScriptingLanguage + { + None, + CSharp + } + + public interface IGenerator { + bool SyncIfNeeded(IEnumerable affectedFiles, IEnumerable reimportedFiles); + void Sync(); + bool HasSolutionBeenGenerated(); + string SolutionFile(); + string ProjectDirectory { get; } + void GenerateAll(bool generateAll); + bool IsSupportedFile(string path); + } + + public interface IAssemblyNameProvider + { + string GetAssemblyNameFromScriptPath(string path); + IEnumerable GetAllAssemblies(Func shouldFileBePartOfSolution); + IEnumerable GetAllAssetPaths(); + UnityEditor.PackageManager.PackageInfo FindForAssetPath(string assetPath); + } + + public struct TestSettings { + public bool ShouldSync; + public Dictionary SyncPath; + } + + class AssemblyNameProvider : IAssemblyNameProvider + { + public string GetAssemblyNameFromScriptPath(string path) + { + return CompilationPipeline.GetAssemblyNameFromScriptPath(path); + } + + public IEnumerable GetAllAssemblies(Func shouldFileBePartOfSolution) + { + return CompilationPipeline.GetAssemblies().Where(i => 0 < i.sourceFiles.Length && i.sourceFiles.Any(shouldFileBePartOfSolution)); + } + + public IEnumerable GetAllAssetPaths() + { + return AssetDatabase.GetAllAssetPaths(); + } + + public UnityEditor.PackageManager.PackageInfo FindForAssetPath(string assetPath) + { + return UnityEditor.PackageManager.PackageInfo.FindForAssetPath(assetPath); + } + } + + public class ProjectGeneration : IGenerator + { + public static readonly string MSBuildNamespaceUri = "http://schemas.microsoft.com/developer/msbuild/2003"; + + const string k_WindowsNewline = "\r\n"; + + string m_SolutionProjectEntryTemplate = string.Join("\r\n", + @"Project(""{{{0}}}"") = ""{1}"", ""{2}"", ""{{{3}}}""", + @"EndProject").Replace(" ", "\t"); + + string m_SolutionProjectConfigurationTemplate = string.Join("\r\n", + @" {{{0}}}.Debug|Any CPU.ActiveCfg = Debug|Any CPU", + @" {{{0}}}.Debug|Any CPU.Build.0 = Debug|Any CPU", + @" {{{0}}}.Release|Any CPU.ActiveCfg = Release|Any CPU", + @" {{{0}}}.Release|Any CPU.Build.0 = Release|Any CPU").Replace(" ", "\t"); + + static readonly string[] k_ReimportSyncExtensions = { ".dll", ".asmdef" }; + + static readonly Regex k_ScriptReferenceExpression = new Regex( + @"^Library.ScriptAssemblies.(?(?.*)\.dll$)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + string[] m_ProjectSupportedExtensions = new string[0]; + string[] m_BuiltinSupportedExtensions = new string[0]; + + public string ProjectDirectory { get; } + + public TestSettings Settings { get; set; } + + readonly string m_ProjectName; + readonly IAssemblyNameProvider m_AssemblyNameProvider; + bool m_ShouldGenerateAll; + + public ProjectGeneration() : this(Directory.GetParent(Application.dataPath).FullName, new AssemblyNameProvider()) + { + } + + public ProjectGeneration(string tempDirectory) : this(tempDirectory, new AssemblyNameProvider()) { + } + + public ProjectGeneration(string tempDirectory, IAssemblyNameProvider assemblyNameProvider) { + Settings = new TestSettings { ShouldSync = true }; + ProjectDirectory = tempDirectory.Replace('\\', '/'); + m_ProjectName = Path.GetFileName(ProjectDirectory); + m_AssemblyNameProvider = assemblyNameProvider; + + SetupProjectSupportedExtensions(); + } + + public void GenerateAll(bool generateAll) + { + m_ShouldGenerateAll = generateAll; + } + + /// + /// Syncs the scripting solution if any affected files are relevant. + /// + /// + /// Whether the solution was synced. + /// + /// + /// A set of files whose status has changed + /// + /// + /// A set of files that got reimported + /// + public bool SyncIfNeeded(IEnumerable affectedFiles, IEnumerable reimportedFiles) + { + SetupProjectSupportedExtensions(); + + // Don't sync if we haven't synced before + if (HasSolutionBeenGenerated() && HasFilesBeenModified(affectedFiles, reimportedFiles)) + { + Sync(); + return true; + } + return false; + } + + bool HasFilesBeenModified(IEnumerable affectedFiles, IEnumerable reimportedFiles) + { + return affectedFiles.Any(ShouldFileBePartOfSolution) || reimportedFiles.Any(ShouldSyncOnReimportedAsset); + } + + static bool ShouldSyncOnReimportedAsset(string asset) + { + return k_ReimportSyncExtensions.Contains(new FileInfo(asset).Extension); + } + + public void Sync() + { + SetupProjectSupportedExtensions(); + bool externalCodeAlreadyGeneratedProjects = OnPreGeneratingCSProjectFiles(); + + if (!externalCodeAlreadyGeneratedProjects) + { + GenerateAndWriteSolutionAndProjects(); + } + OnGeneratedCSProjectFiles(); + } + + public bool HasSolutionBeenGenerated() + { + return File.Exists(SolutionFile()); + } + + void SetupProjectSupportedExtensions() + { + m_ProjectSupportedExtensions = EditorSettings.projectGenerationUserExtensions; + m_BuiltinSupportedExtensions = EditorSettings.projectGenerationBuiltinExtensions; + } + + bool ShouldFileBePartOfSolution(string file) + { + // Exclude files coming from packages except if they are internalized. + if (!m_ShouldGenerateAll && IsInternalizedPackagePath(file)) + { + return false; + } + + return IsSupportedFile(file); + } + + static string GetExtensionWithoutDot(string path) + { + // Prevent re-processing and information loss + if (!Path.HasExtension(path)) + return path; + + return Path + .GetExtension(path) + .TrimStart('.') + .ToLower(); + } + + public bool IsSupportedFile(string path) + { + var extension = GetExtensionWithoutDot(path); + + // Dll's are not scripts but still need to be included + if (extension == "dll") + return true; + + if (extension == "asmdef") + return true; + + if (m_BuiltinSupportedExtensions.Contains(extension)) + return true; + + if (m_ProjectSupportedExtensions.Contains(extension)) + return true; + + return false; + } + + static ScriptingLanguage ScriptingLanguageFor(Assembly island) + { + var files = island.sourceFiles; + + if (files.Length == 0) + return ScriptingLanguage.None; + + return ScriptingLanguageFor(files[0]); + } + + static ScriptingLanguage ScriptingLanguageFor(string path) + { + return GetExtensionWithoutDot(path) == "cs" ? ScriptingLanguage.CSharp : ScriptingLanguage.None; + } + + static List SafeGetTypes(System.Reflection.Assembly a) + { + var ret = new List(); + + try + { + ret = a.GetTypes().ToList(); + } + catch (System.Reflection.ReflectionTypeLoadException rtl) + { + ret = rtl.Types.ToList(); + } + catch (Exception) + { + return new List(); + } + + return ret.Where(r => r != null).ToList(); + } + + public void GenerateAndWriteSolutionAndProjects() + { + // Only synchronize islands that have associated source files and ones that we actually want in the project. + // This also filters out DLLs coming from .asmdef files in packages. + var assemblies = m_AssemblyNameProvider.GetAllAssemblies(ShouldFileBePartOfSolution); + + var allAssetProjectParts = GenerateAllAssetProjectParts(); + + var monoIslands = assemblies.ToList(); + + SyncSolution(monoIslands); + var allProjectIslands = RelevantIslandsForMode(monoIslands).ToList(); + foreach (Assembly assembly in allProjectIslands) + { + var responseFileData = ParseResponseFileData(assembly); + SyncProject(assembly, allAssetProjectParts, responseFileData, allProjectIslands); + } + } + + IEnumerable ParseResponseFileData(Assembly assembly) + { + var systemReferenceDirectories = CompilationPipeline.GetSystemAssemblyDirectories(assembly.compilerOptions.ApiCompatibilityLevel); + + Dictionary responseFilesData = assembly.compilerOptions.ResponseFiles.ToDictionary(x => x, x => CompilationPipeline.ParseResponseFile( + Path.Combine(ProjectDirectory, x), + ProjectDirectory, + systemReferenceDirectories + )); + + Dictionary responseFilesWithErrors = responseFilesData.Where(x => x.Value.Errors.Any()) + .ToDictionary(x => x.Key, x => x.Value); + + if (responseFilesWithErrors.Any()) + { + foreach (var error in responseFilesWithErrors) + foreach (var valueError in error.Value.Errors) + { + Debug.LogError($"{error.Key} Parse Error : {valueError}"); + } + } + + return responseFilesData.Select(x => x.Value); + } + + Dictionary GenerateAllAssetProjectParts() + { + Dictionary stringBuilders = new Dictionary(); + + foreach (string asset in m_AssemblyNameProvider.GetAllAssetPaths()) + { + // Exclude files coming from packages except if they are internalized. + if (!m_ShouldGenerateAll && IsInternalizedPackagePath(asset)) + { + continue; + } + + if (IsSupportedFile(asset) && ScriptingLanguage.None == ScriptingLanguageFor(asset)) + { + // Find assembly the asset belongs to by adding script extension and using compilation pipeline. + var assemblyName = m_AssemblyNameProvider.GetAssemblyNameFromScriptPath(asset + ".cs"); + + if (string.IsNullOrEmpty(assemblyName)) + { + continue; + } + + assemblyName = FileUtility.FileNameWithoutExtension(assemblyName); + + if (!stringBuilders.TryGetValue(assemblyName, out var projectBuilder)) + { + projectBuilder = new StringBuilder(); + stringBuilders[assemblyName] = projectBuilder; + } + + projectBuilder.Append(" ").Append(k_WindowsNewline); + } + } + + var result = new Dictionary(); + + foreach (var entry in stringBuilders) + result[entry.Key] = entry.Value.ToString(); + + return result; + } + + bool IsInternalizedPackagePath(string file) + { + if (string.IsNullOrWhiteSpace(file)) + { + return false; + } + + var packageInfo = m_AssemblyNameProvider.FindForAssetPath(file); + if (packageInfo == null) { + return false; + } + var packageSource = packageInfo.source; + return packageSource != PackageSource.Embedded && packageSource != PackageSource.Local; + } + + void SyncProject( + Assembly island, + Dictionary allAssetsProjectParts, + IEnumerable responseFilesData, + List allProjectIslands) + { + SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, allAssetsProjectParts, responseFilesData, allProjectIslands)); + } + + void SyncProjectFileIfNotChanged(string path, string newContents) + { + if (Path.GetExtension(path) == ".csproj") + { + newContents = OnGeneratedCSProject(path, newContents); + } + + SyncFileIfNotChanged(path, newContents); + } + + void SyncSolutionFileIfNotChanged(string path, string newContents) + { + newContents = OnGeneratedSlnSolution(path, newContents); + + SyncFileIfNotChanged(path, newContents); + } + + static void OnGeneratedCSProjectFiles() + { + IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) + .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + var args = new object[0]; + foreach (var type in types) + { + var method = type.GetMethod("OnGeneratedCSProjectFiles", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + if (method == null) + { + continue; + } + method.Invoke(null, args); + } + } + + static bool OnPreGeneratingCSProjectFiles() + { + IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) + .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + bool result = false; + foreach (var type in types) + { + var args = new object[0]; + var method = type.GetMethod("OnPreGeneratingCSProjectFiles", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + if (method == null) + { + continue; + } + var returnValue = method.Invoke(null, args); + if (method.ReturnType == typeof(bool)) + { + result |= (bool)returnValue; + } + } + return result; + } + + static string OnGeneratedCSProject(string path, string content) + { + IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) + .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + foreach (var type in types) + { + var args = new [] { path, content }; + var method = type.GetMethod("OnGeneratedCSProject", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + if (method == null) + { + continue; + } + var returnValue = method.Invoke(null, args); + if (method.ReturnType == typeof(string)) + { + content = (string)returnValue; + } + } + return content; + } + + static string OnGeneratedSlnSolution(string path, string content) + { + IEnumerable types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => SafeGetTypes(x)) + .Where(x => typeof(AssetPostprocessor).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract); + foreach (var type in types) + { + var args = new [] { path, content }; + var method = type.GetMethod("OnGeneratedSlnSolution", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + if (method == null) + { + continue; + } + var returnValue = method.Invoke(null, args); + if (method.ReturnType == typeof(string)) + { + content = (string)returnValue; + } + } + return content; + } + + void SyncFileIfNotChanged(string filename, string newContents) + { + if (File.Exists(filename) && + newContents == File.ReadAllText(filename)) + { + return; + } + + if (Settings.ShouldSync) + { + File.WriteAllText(filename, newContents, Encoding.UTF8); + } + else + { + var utf8 = Encoding.UTF8; + byte[] utfBytes = utf8.GetBytes(newContents); + Settings.SyncPath[filename] = utf8.GetString(utfBytes, 0, utfBytes.Length); + } + } + + string ProjectText(Assembly assembly, + Dictionary allAssetsProjectParts, + IEnumerable responseFilesData, + List allProjectIslands) + { + var projectBuilder = new StringBuilder(ProjectHeader(assembly, responseFilesData)); + var references = new List(); + var projectReferences = new List(); + + projectBuilder.Append(@" ").Append(k_WindowsNewline); + foreach (string file in assembly.sourceFiles) + { + if (!ShouldFileBePartOfSolution(file)) + continue; + + var extension = Path.GetExtension(file).ToLower(); + var fullFile = EscapedRelativePathFor(file); + if (".dll" != extension) + { + projectBuilder.Append(" ").Append(k_WindowsNewline); + } + else + { + references.Add(fullFile); + } + } + projectBuilder.Append(@" ").Append(k_WindowsNewline); + + var assemblyName = FileUtility.FileNameWithoutExtension(assembly.outputPath); + + projectBuilder.Append(@" ").Append(k_WindowsNewline); + // Append additional non-script files that should be included in project generation. + if (allAssetsProjectParts.TryGetValue(assemblyName, out var additionalAssetsForProject)) + projectBuilder.Append(additionalAssetsForProject); + + var islandRefs = references.Union(assembly.allReferences); + + foreach (string reference in islandRefs) + { + if (reference.EndsWith("/UnityEditor.dll", StringComparison.Ordinal) + || reference.EndsWith("/UnityEngine.dll", StringComparison.Ordinal) + || reference.EndsWith("\\UnityEditor.dll", StringComparison.Ordinal) + || reference.EndsWith("\\UnityEngine.dll", StringComparison.Ordinal)) + continue; + + var match = k_ScriptReferenceExpression.Match(reference); + if (match.Success) + { + // assume csharp language + // Add a reference to a project except if it's a reference to a script assembly + // that we are not generating a project for. This will be the case for assemblies + // coming from .assembly.json files in non-internalized packages. + var dllName = match.Groups["dllname"].Value; + if (allProjectIslands.Any(i => Path.GetFileName(i.outputPath) == dllName)) + { + projectReferences.Add(match); + continue; + } + } + + string fullReference = Path.IsPathRooted(reference) ? reference : Path.Combine(ProjectDirectory, reference); + + AppendReference(fullReference, projectBuilder); + } + + var responseRefs = responseFilesData.SelectMany(x => x.FullPathReferences.Select(r => r)); + foreach (var reference in responseRefs) + { + AppendReference(reference, projectBuilder); + } + projectBuilder.Append(@" ").Append(k_WindowsNewline); + + if (0 < projectReferences.Count) + { + projectBuilder.Append(@" ").Append(k_WindowsNewline); + foreach (Match reference in projectReferences) + { + var referencedProject = reference.Groups["project"].Value; + + projectBuilder.Append(" ").Append(k_WindowsNewline); + projectBuilder.Append(" {").Append(ProjectGuid(Path.Combine("Temp", reference.Groups["project"].Value + ".dll"))).Append("}").Append(k_WindowsNewline); + projectBuilder.Append(" ").Append(referencedProject).Append("").Append(k_WindowsNewline); + projectBuilder.Append(" ").Append(k_WindowsNewline); + } + projectBuilder.Append(@" ").Append(k_WindowsNewline); + } + + projectBuilder.Append(ProjectFooter()); + return projectBuilder.ToString(); + } + + static string XmlFilename(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + path = path.Replace(@"%", "%25"); + path = path.Replace(@";", "%3b"); + + return XmlEscape(path); + } + + static string XmlEscape(string s) + { + return SecurityElement.Escape(s); + } + + void AppendReference(string fullReference, StringBuilder projectBuilder) + { + var escapedFullPath = EscapedRelativePathFor(fullReference); + projectBuilder.Append(" ").Append(k_WindowsNewline); + projectBuilder.Append(" ").Append(escapedFullPath).Append("").Append(k_WindowsNewline); + projectBuilder.Append(" ").Append(k_WindowsNewline); + } + + public string ProjectFile(Assembly assembly) + { + return Path.Combine(ProjectDirectory, $"{FileUtility.FileNameWithoutExtension(assembly.outputPath)}.csproj"); + } + + private static readonly Regex InvalidCharactersRegexPattern = new Regex(@"\?|&|\*|""|<|>|\||#|%|\^|;" + (VisualStudioEditor.IsWindows ? "" : "|:")); + public string SolutionFile() + { + return Path.Combine(FileUtility.Normalize(ProjectDirectory), $"{InvalidCharactersRegexPattern.Replace(m_ProjectName,"_")}.sln"); + } + + string ProjectHeader( + Assembly island, + IEnumerable responseFilesData + ) + { + var toolsVersion = "4.0"; + var productVersion = "10.0.20506"; + const string baseDirectory = "."; + + var targetFrameworkVersion = "v4.7.1"; + var targetLanguageVersion = "latest"; + + var projectType = ProjectTypeOf(island.outputPath); + + var arguments = new object[] + { + toolsVersion, productVersion, ProjectGuid(island.outputPath), + XmlFilename(FileUtility.Normalize(InternalEditorUtility.GetEngineAssemblyPath())), + XmlFilename(FileUtility.Normalize(InternalEditorUtility.GetEditorAssemblyPath())), + string.Join(";", new[] { "DEBUG", "TRACE" }.Concat(EditorUserBuildSettings.activeScriptCompilationDefines).Concat(island.defines).Concat(responseFilesData.SelectMany(x => x.Defines)).Distinct().ToArray()), + MSBuildNamespaceUri, + FileUtility.FileNameWithoutExtension(island.outputPath), + EditorSettings.projectGenerationRootNamespace, + targetFrameworkVersion, + targetLanguageVersion, + baseDirectory, + island.compilerOptions.AllowUnsafeCode | responseFilesData.Any(x => x.Unsafe), + // flavoring + projectType + ":" + (int)projectType, + EditorUserBuildSettings.activeBuildTarget + ":" + (int)EditorUserBuildSettings.activeBuildTarget, + Application.unityVersion, + }; + + try + { + return string.Format(GetProjectHeaderTemplate(), arguments); + } + catch (Exception) + { + throw new NotSupportedException("Failed creating c# project because the c# project header did not have the correct amount of arguments, which is " + arguments.Length); + } + } + + private enum ProjectType + { + GamePlugins = 3, + Game = 1, + EditorPlugins = 7, + Editor = 5, + } + + private static ProjectType ProjectTypeOf(string fileName) + { + var plugins = fileName.Contains("firstpass"); + var editor = fileName.Contains("Editor"); + + if (plugins && editor) + return ProjectType.EditorPlugins; + if (plugins) + return ProjectType.GamePlugins; + if (editor) + return ProjectType.Editor; + + return ProjectType.Game; + } + + static string GetSolutionText() + { + return string.Join("\r\n", + @"", + @"Microsoft Visual Studio Solution File, Format Version {0}", + @"# Visual Studio {1}", + @"{2}", + @"Global", + @" GlobalSection(SolutionConfigurationPlatforms) = preSolution", + @" Debug|Any CPU = Debug|Any CPU", + @" Release|Any CPU = Release|Any CPU", + @" EndGlobalSection", + @" GlobalSection(ProjectConfigurationPlatforms) = postSolution", + @"{3}", + @" EndGlobalSection", + @"{4}", + @"EndGlobal", + @"").Replace(" ", "\t"); + } + + static string GetProjectFooterTemplate() + { + return string.Join("\r\n", + @" ", + @" ", + @" ", + @"", + @""); + } + + string GetProjectHeaderTemplate() + { + var header = new[] + { + @"", + @"", + @" ", + @" {10}", + @" ", + @" ", + @" Debug", + @" AnyCPU", + @" {1}", + @" 2.0", + @" {8}", + @" {{{2}}}", + @" Library", + @" Properties", + @" {7}", + @" {9}", + @" 512", + @" {11}", + @" ", + @" ", + @" true", + @" full", + @" false", + @" Temp\bin\Debug\", + @" {5}", + @" prompt", + @" 4", + @" 0169", + @" {12}", + @" ", + @" ", + @" pdbonly", + @" true", + @" Temp\bin\Release\", + @" prompt", + @" 4", + @" 0169", + @" {12}", + @" " + }; + + var forceExplicitReferences = new[] + { + @" ", + @" true", + @" true", + @" false", + @" false", + @" false", + @" " + }; + + var flavoring = new[] + { + @" ", + @" {{E097FAD1-6243-4DAD-9C02-E9B9EFC3FFC1}};{{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}}", + @" Package", + @" {13}", + @" {14}", + @" {15}", + @" " + }; + + var footer = new[] + { + @" ", + @" ", + @" {3}", + @" ", + @" ", + @" {4}", + @" ", + @" ", + @"" + }; + + var lines = header + .Concat(forceExplicitReferences) + .Concat(flavoring) + .ToList(); + + // Only add analyzer block for compatible Visual Studio + if (CodeEditor.CurrentEditor is VisualStudioEditor editor && editor.TryGetVisualStudioInstallationForPath(CodeEditor.CurrentEditorInstallation, out var installation)) + { + if (installation.SupportsAnalyzers) + { + var analyzers = installation.GetAnalyzers(); + if (analyzers != null && analyzers.Length > 0) + { + lines.Add(@" "); + foreach (var analyzer in analyzers) + lines.Add(string.Format(@" ", EscapedRelativePathFor(analyzer))); + lines.Add(@" "); + } + } + } + + return string.Join("\r\n", lines + .Concat(footer)); + } + + void SyncSolution(IEnumerable islands) + { + if (InvalidCharactersRegexPattern.IsMatch(ProjectDirectory)) + Debug.LogWarning("Project path contains special characters, which can be an issue when opening Visual Studio"); + + var solutionFile = SolutionFile(); + var previousSolution = File.Exists(solutionFile) ? SolutionParser.ParseSolutionFile(solutionFile) : null; + SyncSolutionFileIfNotChanged(solutionFile, SolutionText(islands, previousSolution)); + } + + string SolutionText(IEnumerable islands, Solution previousSolution = null) + { + const string fileversion = "12.00"; + const string vsversion = "15"; + + var relevantIslands = RelevantIslandsForMode(islands); + var generatedProjects = ToProjectEntries(relevantIslands); + + SolutionProperties[] properties = null; + + // First, add all projects generated by Unity to the solution + var projects = new List(); + projects.AddRange(generatedProjects); + + if (previousSolution != null) + { + // Add all projects that were previously in the solution and that are not generated by Unity, nor generated in the project root directory + var externalProjects = previousSolution.Projects + .Where(p => !FileUtility.IsFileInProjectDirectory(p.FileName)) + .Where(p => generatedProjects.All(gp => gp.FileName != p.FileName)); + + projects.AddRange(externalProjects); + properties = previousSolution.Properties; + } + + string propertiesText = GetPropertiesText(properties); + string projectEntriesText = GetProjectEntriesText(projects); + string projectConfigurationsText = string.Join(k_WindowsNewline, projects.Select(p => GetProjectActiveConfigurations(p.ProjectGuid)).ToArray()); + return string.Format(GetSolutionText(), fileversion, vsversion, projectEntriesText, projectConfigurationsText, propertiesText); + } + + static IEnumerable RelevantIslandsForMode(IEnumerable islands) + { + IEnumerable relevantIslands = islands.Where(i => ScriptingLanguage.CSharp == ScriptingLanguageFor(i)); + return relevantIslands; + } + + private string GetPropertiesText(SolutionProperties[] array) + { + if (array == null || array.Length == 0) + { + // HideSolution by default + array = new SolutionProperties[] { + new SolutionProperties() { + Name = "SolutionProperties", + Type = "preSolution", + Entries = new List>() { new KeyValuePair ("HideSolutionNode", "FALSE") } + } + }; + } + var result = new StringBuilder(); + + for (var i = 0; i 0) + result.Append(k_WindowsNewline); + + var properties = array[i]; + + result.Append($"\tGlobalSection({properties.Name}) = {properties.Type}"); + result.Append(k_WindowsNewline); + + foreach (var entry in properties.Entries) + { + result.Append($"\t\t{entry.Key} = {entry.Value}"); + result.Append(k_WindowsNewline); + } + + result.Append("\tEndGlobalSection"); + } + + return result.ToString(); + } + + /// + /// Get a Project("{guid}") = "MyProject", "MyProject.unityproj", "{projectguid}" + /// entry for each relevant language + /// + string GetProjectEntriesText(IEnumerable entries) + { + var projectEntries = entries.Select(entry => string.Format( + m_SolutionProjectEntryTemplate, + entry.ProjectFactoryGuid, entry.Name, entry.FileName, entry.ProjectGuid + )); + + return string.Join(k_WindowsNewline, projectEntries.ToArray()); + } + + IEnumerable ToProjectEntries(IEnumerable islands) + { + foreach (var island in islands) + yield return new SolutionProjectEntry() + { + ProjectFactoryGuid = SolutionGuid(island), + Name = FileUtility.FileNameWithoutExtension(island.outputPath), + FileName = Path.GetFileName(ProjectFile(island)), + ProjectGuid = ProjectGuid(island.outputPath) + }; + } + + /// + /// Generate the active configuration string for a given project guid + /// + string GetProjectActiveConfigurations(string projectGuid) + { + return string.Format( + m_SolutionProjectConfigurationTemplate, + projectGuid); + } + + string EscapedRelativePathFor(string file) + { + var projectDir = FileUtility.Normalize(ProjectDirectory); + file = FileUtility.Normalize(file); + var path = SkipPathPrefix(file, projectDir); + + var packageInfo = m_AssemblyNameProvider.FindForAssetPath(path.Replace('\\', '/')); + if (packageInfo != null) { + // We have to normalize the path, because the PackageManagerRemapper assumes + // dir seperators will be os specific. + var absolutePath = Path.GetFullPath(FileUtility.Normalize(path)); + path = SkipPathPrefix(absolutePath, projectDir); + } + + return XmlFilename(path); + } + + static string SkipPathPrefix(string path, string prefix) + { + if (path.StartsWith($"{prefix}{Path.DirectorySeparatorChar}") && (path.Length > prefix.Length)) + return path.Substring(prefix.Length + 1); + return path; + } + + string ProjectGuid(string assembly) + { + return SolutionGuidGenerator.GuidForProject(m_ProjectName + FileUtility.FileNameWithoutExtension(assembly)); + } + + string SolutionGuid(Assembly island) + { + return SolutionGuidGenerator.GuidForSolution(m_ProjectName, ScriptingLanguageFor(island)); + } + + static string ProjectFooter() + { + return GetProjectFooterTemplate(); + } + + static string GetProjectExtension() + { + return ".csproj"; + } + } + + public static class SolutionGuidGenerator + { + public static string GuidForProject(string projectName) + { + return ComputeGuidHashFor(projectName + "salt"); + } + + public static string GuidForSolution(string projectName, ScriptingLanguage language) + { + if (language == ScriptingLanguage.CSharp) + { + // GUID for a C# class library: http://www.codeproject.com/Reference/720512/List-of-Visual-Studio-Project-Type-GUIDs + return "FAE04EC0-301F-11D3-BF4B-00C04F79EFBC"; + } + + return ComputeGuidHashFor(projectName); + } + + static string ComputeGuidHashFor(string input) + { + var hash = MD5.Create().ComputeHash(Encoding.Default.GetBytes(input)); + return HashAsGuid(HashToString(hash)); + } + + static string HashAsGuid(string hash) + { + var guid = hash.Substring(0, 8) + "-" + hash.Substring(8, 4) + "-" + hash.Substring(12, 4) + "-" + hash.Substring(16, 4) + "-" + hash.Substring(20, 12); + return guid.ToUpper(); + } + + static string HashToString(byte[] bs) + { + var sb = new StringBuilder(); + foreach (byte b in bs) + sb.Append(b.ToString("x2")); + return sb.ToString(); + } + } +} diff --git a/Editor/ProjectGeneration.cs.meta b/Editor/ProjectGeneration.cs.meta index c5153ae..645df67 100644 --- a/Editor/ProjectGeneration.cs.meta +++ b/Editor/ProjectGeneration.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: c55bbb5ab4b342946980281be9e63c1a -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: c55bbb5ab4b342946980281be9e63c1a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Solution.cs b/Editor/Solution.cs new file mode 100644 index 0000000..1db7ed2 --- /dev/null +++ b/Editor/Solution.cs @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal class Solution + { + public SolutionProjectEntry[] Projects { get; set; } + public SolutionProperties[] Properties { get; set; } + } +} diff --git a/Editor/Solution.cs.meta b/Editor/Solution.cs.meta new file mode 100644 index 0000000..6e88569 --- /dev/null +++ b/Editor/Solution.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: af4c2c762e1d8e949a6bc458973df6e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/SolutionParser.cs b/Editor/SolutionParser.cs new file mode 100644 index 0000000..ff5aa00 --- /dev/null +++ b/Editor/SolutionParser.cs @@ -0,0 +1,80 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal static class SolutionParser + { + // Compared to the bridge implementation, we are not returning "{" "}" from Guids + private static readonly Regex ProjectDeclaration = new Regex(@"Project\(\""{(?.*?)}\""\)\s+=\s+\""(?.*?)\"",\s+\""(?.*?)\"",\s+\""{(?.*?)}\""(?.*?)\bEndProject\b", RegexOptions.Singleline | RegexOptions.ExplicitCapture); + private static readonly Regex PropertiesDeclaration = new Regex(@"GlobalSection\((?[\w]+Properties)\)\s+=\s+(?(?:post|pre)Solution)(?.*?)EndGlobalSection", RegexOptions.Singleline | RegexOptions.ExplicitCapture); + private static readonly Regex PropertiesEntryDeclaration = new Regex(@"^\s*(?.*?)=(?.*?)$", RegexOptions.Multiline | RegexOptions.ExplicitCapture); + + public static Solution ParseSolutionFile(string filename) + { + return ParseSolutionContent(File.ReadAllText(filename)); + } + + public static Solution ParseSolutionContent(string content) + { + return new Solution + { + Projects = ParseSolutionProjects(content), + Properties = ParseSolutionProperties(content) + }; + } + + private static SolutionProjectEntry[] ParseSolutionProjects(string content) + { + var projects = new List(); + var mc = ProjectDeclaration.Matches(content); + + foreach (Match match in mc) + { + projects.Add(new SolutionProjectEntry + { + ProjectFactoryGuid = match.Groups["projectFactoryGuid"].Value, + Name = match.Groups["name"].Value, + FileName = match.Groups["fileName"].Value, + ProjectGuid = match.Groups["projectGuid"].Value, + }); + } + + return projects.ToArray(); + } + + private static SolutionProperties[] ParseSolutionProperties(string content) + { + var properties = new List(); + var mc = PropertiesDeclaration.Matches(content); + + foreach (Match match in mc) + { + var sp = new SolutionProperties + { + Entries = new List>(), + Name = match.Groups["name"].Value, + Type = match.Groups["type"].Value + }; + + var entries = match.Groups["entries"].Value; + var mec = PropertiesEntryDeclaration.Matches(entries); + foreach (Match entry in mec) + { + var key = entry.Groups["key"].Value.Trim(); + var value = entry.Groups["value"].Value.Trim(); + sp.Entries.Add(new KeyValuePair(key, value)); + } + + properties.Add(sp); + } + + return properties.ToArray(); + } + } +} diff --git a/Editor/SolutionParser.cs.meta b/Editor/SolutionParser.cs.meta new file mode 100644 index 0000000..208d8a8 --- /dev/null +++ b/Editor/SolutionParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fbbb1ee655846b043baf6c3502b5ce49 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/SolutionProjectEntry.cs b/Editor/SolutionProjectEntry.cs new file mode 100644 index 0000000..4319b94 --- /dev/null +++ b/Editor/SolutionProjectEntry.cs @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal class SolutionProjectEntry + { + public string ProjectFactoryGuid { get; set; } + public string Name { get; set; } + public string FileName { get; set; } + public string ProjectGuid { get; set; } + } +} diff --git a/Editor/SolutionProjectEntry.cs.meta b/Editor/SolutionProjectEntry.cs.meta new file mode 100644 index 0000000..c125a32 --- /dev/null +++ b/Editor/SolutionProjectEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c1b8a755d2c97640bbb207c43f4cf61 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/SolutionProperties.cs b/Editor/SolutionProperties.cs new file mode 100644 index 0000000..c0cf791 --- /dev/null +++ b/Editor/SolutionProperties.cs @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System.Collections.Generic; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal class SolutionProperties + { + public string Name { get; set; } + public IList> Entries { get; set; } + public string Type { get; set; } + } +} diff --git a/Editor/SolutionProperties.cs.meta b/Editor/SolutionProperties.cs.meta new file mode 100644 index 0000000..b4eedd1 --- /dev/null +++ b/Editor/SolutionProperties.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 829d4d6bc39fd1044ba4c5fc2a9c911f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Symbols.cs b/Editor/Symbols.cs new file mode 100644 index 0000000..076fec6 --- /dev/null +++ b/Editor/Symbols.cs @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.IO; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal static class Symbols + { + public static bool IsPortableSymbolFile(string pdbFile) + { + try + { + using (var stream = File.OpenRead(pdbFile)) + { + return stream.ReadByte() == 'B' + && stream.ReadByte() == 'S' + && stream.ReadByte() == 'J' + && stream.ReadByte() == 'B'; + } + } + catch (Exception) + { + return false; + } + } + } +} diff --git a/Editor/Symbols.cs.meta b/Editor/Symbols.cs.meta new file mode 100644 index 0000000..0923a63 --- /dev/null +++ b/Editor/Symbols.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9308b762484008498bb5cd1886aa491 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Utility.cs b/Editor/Utility.cs deleted file mode 100644 index 2e773b2..0000000 --- a/Editor/Utility.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace VisualStudioEditor -{ - public static class Utility - { - public static string FileNameWithoutExtension(string path) - { - if (string.IsNullOrEmpty(path)) - { - return ""; - } - - var indexOfDot = -1; - var indexOfSlash = 0; - for (var i = path.Length - 1; i >= 0; i--) - { - if (indexOfDot == -1 && path[i] == '.') - { - indexOfDot = i; - } - if (indexOfSlash == 0 && path[i] == '/' || path[i] == '\\') - { - indexOfSlash = i + 1; - break; - } - } - - if (indexOfDot == -1) - { - indexOfDot = path.Length - 1; - } - - return path.Substring(indexOfSlash, indexOfDot - indexOfSlash); - } - } -} \ No newline at end of file diff --git a/Editor/VSEditor.cs b/Editor/VSEditor.cs deleted file mode 100644 index 5973145..0000000 --- a/Editor/VSEditor.cs +++ /dev/null @@ -1,335 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using Microsoft.Win32; -using UnityEditor; -using UnityEngine; -using Debug = System.Diagnostics.Debug; -using Unity.CodeEditor; -using System.Runtime.InteropServices; - - -namespace VisualStudioEditor -{ - public enum VisualStudioVersion - { - Invalid = 0, - VisualStudio2008 = 9, - VisualStudio2010 = 10, - VisualStudio2012 = 11, - VisualStudio2013 = 12, - VisualStudio2015 = 14, - VisualStudio2017 = 15, - VisualStudio2019 = 16, - } - - [InitializeOnLoad] - public class VSEditor : IExternalCodeEditor - { - static readonly string k_ExpressNotSupportedMessage = L10n.Tr( - "Unfortunately Visual Studio Express does not allow itself to be controlled by external applications. " + - "You can still use it by manually opening the Visual Studio project file, but Unity cannot automatically open files for you when you doubleclick them. " + - "\n(This does work with Visual Studio Pro)" - ); - - static VSEditor() - { - try - { - InstalledVisualStudios = Discovery.GetInstalledVisualStudios(); - } - catch (Exception ex) - { - UnityEngine.Debug.Log($@"Error detecting Visual Studio installations: {ex.Message}{Environment.NewLine}{ex.StackTrace}"); - InstalledVisualStudios = new Dictionary(); - } - var editor = new VSEditor(new Discovery(), new ProjectGeneration()); - CodeEditor.Register(editor); - var current = CodeEditor.CurrentEditorInstallation; - if (editor.TryGetInstallationForPath(current, out var installation)) - { - if (installation.Name != "MonoDevelop") - { - editor.Initialize(current); - } - return; - } - } - - const string unity_generate_all = "unity_generate_all_csproj"; - IDiscovery m_Discoverability; - IGenerator m_Generation; - CodeEditor.Installation m_Installation; - VSInitializer m_Initializer = new VSInitializer(); - - public VSEditor(IDiscovery discovery, IGenerator projectGeneration) - { - m_Discoverability = discovery; - m_Generation = projectGeneration; - } - - internal static Dictionary InstalledVisualStudios { get; private set; } - - internal static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor; - internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n"; - - public CodeEditor.Installation[] Installations => m_Discoverability.PathCallback(); - - public void CreateIfDoesntExist() - { - if (!m_Generation.HasSolutionBeenGenerated()) - { - m_Generation.Sync(); - } - } - - public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation) - { - var lowerCasePath = editorPath.ToLower(); - if (lowerCasePath.EndsWith("vcsexpress.exe", StringComparison.OrdinalIgnoreCase)) - { - installation = new CodeEditor.Installation - { - Name = "VSExpress", - Path = editorPath - }; - m_Installation = installation; - return true; - } - - if (lowerCasePath.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase) - || lowerCasePath.Replace(" ", "").EndsWith("visualstudio.app", StringComparison.OrdinalIgnoreCase) - || lowerCasePath.Replace(" ", "").EndsWith("visualstudio(preview).app", StringComparison.OrdinalIgnoreCase)) - { - installation = new CodeEditor.Installation - { - Name = "VisualStudio", - Path = editorPath - }; - m_Installation = installation; - return true; - } - - if (lowerCasePath.Contains("monodevelop") - || lowerCasePath.Replace(" ", "").Contains("xamarinstudio")) - { - installation = new CodeEditor.Installation - { - Name = "MonoDevelop", - Path = editorPath - }; - m_Installation = installation; - return true; - } - - installation = default; - m_Installation = installation; - return false; - } - - public void OnGUI() - { - if (m_Installation.Name.Equals("VSExpress")) - { - GUILayout.BeginHorizontal(EditorStyles.helpBox); - GUILayout.Label("", "CN EntryWarn"); - GUILayout.Label(k_ExpressNotSupportedMessage, "WordWrappedLabel"); - GUILayout.EndHorizontal(); - } - - var prevGenerate = EditorPrefs.GetBool(unity_generate_all, false); - var generateAll = EditorGUILayout.Toggle("Generate all .csproj files.", prevGenerate); - if (generateAll != prevGenerate) - { - EditorPrefs.SetBool(unity_generate_all, generateAll); - } - m_Generation.GenerateAll(generateAll); - } - - public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles) - { - m_Generation.SyncIfNeeded(addedFiles.Union(deletedFiles).Union(movedFiles).Union(movedFromFiles), importedFiles); - } - - public void SyncAll() - { - AssetDatabase.Refresh(); - m_Generation.Sync(); - } - - public void Initialize(string editorInstallationPath) - { - m_Initializer.Initialize(editorInstallationPath, InstalledVisualStudios); - } - - public bool OpenProject(string path, int line, int column) - { - if (m_Installation.Name == "MonoDevelop") { - return OpenAppMonoDev(path, line, column); - } - - if (IsOSX) - { - return OpenOSXApp(path, line, column); - } - - if (IsWindows) - { - return OpenWindowsApp(path, line); - } - - return false; - } - - private bool OpenWindowsApp(string path, int line) - { - var comAssetPath = AssetDatabase.FindAssets("COMIntegration a:packages").Select(AssetDatabase.GUIDToAssetPath).First(assetPath => assetPath.Contains("COMIntegration.dom")); - if (string.IsNullOrWhiteSpace(comAssetPath)) // This may be called too early where the asset database has not replicated this information yet. - { - return false; - } - UnityEditor.PackageManager.PackageInfo packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(comAssetPath); - var progpath = packageInfo.resolvedPath + comAssetPath.Substring("Packages/com.unity.ide.visualstudio".Length); - string absolutePath = ""; - if (!string.IsNullOrWhiteSpace(path)) - { - absolutePath = Path.GetFullPath(path); - } - - - var solution = GetOrGenerateSolutionFile(path); - solution = solution == "" ? "" : $"\"{solution}\""; - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = progpath, - Arguments = $"\"{CodeEditor.CurrentEditorInstallation}\" \"{absolutePath}\" {solution} {line}", - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - } - }; - var result = process.Start(); - - while (!process.StandardOutput.EndOfStream) - { - var outputLine = process.StandardOutput.ReadLine(); - if (outputLine == "displayProgressBar") - { - EditorUtility.DisplayProgressBar("Opening Visual Studio", "Starting up Visual Studio, this might take some time.", .5f); - } - - if (outputLine == "clearprogressbar") - { - EditorUtility.ClearProgressBar(); - } - } - var errorOutput = process.StandardError.ReadToEnd(); - if (!string.IsNullOrEmpty(errorOutput)) - { - Console.WriteLine("Error: \n" + errorOutput); - } - - process.WaitForExit(); - return result; - } - - bool OpenAppMonoDev(string path, int line, int column) - { - string absolutePath = ""; - if (!string.IsNullOrWhiteSpace(path)) - { - absolutePath = Path.GetFullPath(path); - } - - var solution = GetOrGenerateSolutionFile(path); - solution = solution == "" ? "" : $"\"{solution}\""; - var pathArguments = path == "" ? "" : $"\"{path}\";{line}"; - var fileName = IsOSX ? "open" : CodeEditor.CurrentEditorInstallation; - var arguments = IsOSX - ? $"\"{CodeEditor.CurrentEditorInstallation}\" --args --nologo {solution} {pathArguments}" - : $"--nologo {solution} {pathArguments}"; - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - CreateNoWindow = true, - UseShellExecute = true, - } - }; - - process.Start(); - - return true; - } - - [DllImport ("AppleEventIntegrationPlugin")] - static extern void OpenVisualStudio(string appPath, string solutionPath, string filePath, int line, StringBuilder sb, int sbLength); - - bool OpenOSXApp(string path, int line, int column) - { - string absolutePath = ""; - if (!string.IsNullOrWhiteSpace(path)) - { - absolutePath = Path.GetFullPath(path); - } - - string solution = GetOrGenerateSolutionFile(path); - - StringBuilder sb = new StringBuilder(4096); - - OpenVisualStudio(CodeEditor.CurrentEditorInstallation, solution, absolutePath, line, sb, sb.Capacity); - - Console.WriteLine(sb.ToString()); - - return true; - } - - private string GetOrGenerateSolutionFile(string path) - { - var solution = GetSolutionFile(path); - if (solution == "") - { - m_Generation.Sync(); - solution = GetSolutionFile(path); - } - - return solution; - } - - string GetSolutionFile(string path) - { - if (UnityEditor.Unsupported.IsDeveloperBuild()) - { - var baseFolder = GetBaseUnityDeveloperFolder(); - var lowerPath = path.ToLowerInvariant(); - var isUnitySourceCode = - lowerPath.Contains((baseFolder + "/Runtime").ToLowerInvariant()) - || lowerPath.Contains((baseFolder + "/Editor").ToLowerInvariant()); - - if (isUnitySourceCode) - { - return Path.Combine(baseFolder, "Projects/CSharp/Unity.CSharpProjects.gen.sln"); - } - } - var solutionFile = m_Generation.SolutionFile(); - if (File.Exists(solutionFile)) - { - return solutionFile; - } - return ""; - } - - static string GetBaseUnityDeveloperFolder() - { - return Directory.GetParent(EditorApplication.applicationPath).Parent.Parent.FullName; - } - } -} diff --git a/Editor/VSInitializer.cs b/Editor/VSInitializer.cs deleted file mode 100644 index 41d4809..0000000 --- a/Editor/VSInitializer.cs +++ /dev/null @@ -1,276 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.RegularExpressions; -using Microsoft.Win32; -using UnityEngine; -using Debug = UnityEngine.Debug; - -namespace VisualStudioEditor -{ - internal class VSInitializer - { - public void Initialize(string editorPath, Dictionary installedVisualStudios) - { - switch (Application.platform) { - case RuntimePlatform.OSXEditor: - InitializeVSForMac(editorPath); - break; - case RuntimePlatform.WindowsEditor: - InitializeVisualStudio(editorPath, installedVisualStudios); - break; - } - } - - static void InitializeVSForMac(string externalEditor) - { - if (!IsVSForMac(externalEditor, out var vsfmVersion)) - return; - - var bridgeFile = GetVSForMacBridgeAssembly(externalEditor, vsfmVersion); - if (string.IsNullOrEmpty(bridgeFile) || !File.Exists(bridgeFile)) - { - Debug.Log("Unable to find Tools for Unity bridge dll for Visual Studio for Mac " + externalEditor); - return; - } - - AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(bridgeFile)); - } - - static bool IsVisualStudioForMac(string path) - { - var lowerCasePath = path.ToLower(); - var filename = Path.GetFileName(lowerCasePath).Replace(" ", ""); - return filename.StartsWith("visualstudio") && !filename.Contains("code") && filename.EndsWith(".app"); - } - - static bool IsVSForMac(string externalEditor, out Version vsfmVersion) - { - vsfmVersion = null; - - if (!IsVisualStudioForMac(externalEditor)) - return false; - - // We need to extract the version used by VS for Mac - // to lookup its addin registry - try - { - return GetVSForMacVersion(externalEditor, out vsfmVersion); - } - catch (Exception e) - { - Debug.Log("Failed to read Visual Studio for Mac information"); - Debug.LogException(e); - return false; - } - } - - static bool GetVSForMacVersion(string externalEditor, out Version vsfmVersion) - { - vsfmVersion = null; - - // Read the full VS for Mac version from the plist, it will look like this: - // - // CFBundleShortVersionString - // X.X.X.X - - var plist = Path.Combine(externalEditor, "Contents/Info.plist"); - if (!File.Exists(plist)) - return false; - - const string versionStringRegex = @"\CFBundleShortVersionString\\s+\(?\d+\.\d+\.\d+\.\d+?)\"; - - var file = File.ReadAllText(plist); - var match = Regex.Match(file, versionStringRegex); - var versionGroup = match.Groups["version"]; - if (!versionGroup.Success) - return false; - - vsfmVersion = new Version(versionGroup.Value); - return true; - } - - static void InitializeVisualStudio(string externalEditor, Dictionary installedVisualStudios) - { - if (!externalEditor.Contains("2017")) - { - return; - } - - FindVisualStudio(externalEditor, out var vsVersion, installedVisualStudios); - var bridgeFile = GetVstuBridgeAssembly(vsVersion); - if (bridgeFile == null) - { - Debug.Log("Unable to find bridge dll in registry for Microsoft Visual Studio Tools for Unity for " + externalEditor); - return; - } - if (!File.Exists(bridgeFile)) - { - Debug.Log("Unable to find bridge dll on disk for Microsoft Visual Studio Tools for Unity for " + bridgeFile); - return; - } - - AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(bridgeFile)); - } - - static string GetVstuBridgeAssembly(VisualStudioVersion version) - { - try - { - var vsVersion = string.Empty; - - switch (version) - { - // Starting with VS 15, the registry key is using the VS version - // to avoid taking a dependency on the product name - case VisualStudioVersion.VisualStudio2017: - vsVersion = "15.0"; - break; - case VisualStudioVersion.VisualStudio2019: - vsVersion = "16.0"; - break; - // VS 2015 and under are still installed in the registry - // using their project names - case VisualStudioVersion.VisualStudio2015: - vsVersion = "2015"; - break; - case VisualStudioVersion.VisualStudio2013: - vsVersion = "2013"; - break; - case VisualStudioVersion.VisualStudio2012: - vsVersion = "2012"; - break; - case VisualStudioVersion.VisualStudio2010: - vsVersion = "2010"; - break; - } - - // search first for the current user with a fallback to machine wide setting - return GetVstuBridgePathFromRegistry(vsVersion, true) - ?? GetVstuBridgePathFromRegistry(vsVersion, false); - } - catch (Exception) - { - return null; - } - } - - static string GetVstuBridgePathFromRegistry(string vsVersion, bool currentUser) - { - var registryKey = $@"{(currentUser ? "HKEY_CURRENT_USER" : "HKEY_LOCAL_MACHINE")}\Software\Microsoft\Microsoft Visual Studio {vsVersion} Tools for Unity"; - - return (string)Registry.GetValue(registryKey, "UnityExtensionPath", null); - } - - static void FindVisualStudio(string externalEditor, out VisualStudioVersion vsVersion, Dictionary installedVisualStudios) - { - if (string.IsNullOrEmpty(externalEditor)) - { - vsVersion = VisualStudioVersion.Invalid; - return; - } - - // If it's a VS found through envvars or the registry - var matches = installedVisualStudios.Where(kvp => kvp.Value.Any(v => Path.GetFullPath(v).Equals(Path.GetFullPath(externalEditor), StringComparison.OrdinalIgnoreCase))).ToArray(); - if (matches.Length > 0) - { - vsVersion = matches[0].Key; - return; - } - - // If it's a side-by-side VS selected manually - if (externalEditor.EndsWith("devenv.exe", StringComparison.OrdinalIgnoreCase)) - { - if (TryGetVisualStudioVersion(externalEditor, out vsVersion)) return; - } - - vsVersion = VisualStudioVersion.Invalid; - } - - static bool TryGetVisualStudioVersion(string externalEditor, out VisualStudioVersion vsVersion) - { - switch (ProductVersion(externalEditor).Major) - { - case 9: - vsVersion = VisualStudioVersion.VisualStudio2008; - return true; - case 10: - vsVersion = VisualStudioVersion.VisualStudio2010; - return true; - case 11: - vsVersion = VisualStudioVersion.VisualStudio2012; - return true; - case 12: - vsVersion = VisualStudioVersion.VisualStudio2013; - return true; - case 14: - vsVersion = VisualStudioVersion.VisualStudio2015; - return true; - case 15: - vsVersion = VisualStudioVersion.VisualStudio2017; - return true; - case 16: - vsVersion = VisualStudioVersion.VisualStudio2019; - return true; - } - - vsVersion = VisualStudioVersion.Invalid; - return false; - } - - static Version ProductVersion(string externalEditor) - { - try - { - return new Version(FileVersionInfo.GetVersionInfo(externalEditor).ProductVersion); - } - catch (Exception) - { - return new Version(0, 0); - } - } - - static string GetVSForMacBridgeAssembly(string externalEditor, Version vsfmVersion) - { - // Check first if we're overriden - // Useful when developing UnityVS for Mac - var bridge = Environment.GetEnvironmentVariable("VSTUM_BRIDGE"); - if (!string.IsNullOrEmpty(bridge) && File.Exists(bridge)) - return bridge; - - // Look for installed addin - const string addinBridge = "Editor/SyntaxTree.VisualStudio.Unity.Bridge.dll"; - const string addinName = "MonoDevelop.Unity"; - - // Check if we're installed in the user addins repository - // ~/Library/Application Support/VisualStudio/X.0/LocalInstall/Addins - var localAddins = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.Personal), - "Library/Application Support/VisualStudio/" + vsfmVersion.Major + ".0" + "/LocalInstall/Addins"); - - // In the user addins repository, the addins are suffixed by their versions, like `MonoDevelop.Unity.1.0` - // When installing another local user addin, MD will remove files inside the folder - // So we browse all VSTUM addins, and return the one with a bridge, which is the one MD will load - if (Directory.Exists(localAddins)) - { - foreach (var folder in Directory.GetDirectories(localAddins, addinName + "*", SearchOption.TopDirectoryOnly)) - { - bridge = Path.Combine(folder, addinBridge); - if (File.Exists(bridge)) - return bridge; - } - } - - // Check in Visual Studio.app/ - // In that case the name of the addin is used - bridge = Path.Combine(externalEditor, "Contents/Resources/lib/monodevelop/AddIns/" + addinName + "/" + addinBridge); - if (File.Exists(bridge)) - return bridge; - - return null; - } - } -} diff --git a/Editor/VSWhere.meta b/Editor/VSWhere.meta index 522b5a1..681e580 100644 --- a/Editor/VSWhere.meta +++ b/Editor/VSWhere.meta @@ -1,8 +1,8 @@ -fileFormatVersion: 2 -guid: 5b17896803f77494da73d73448fb6cb4 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 5b17896803f77494da73d73448fb6cb4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/VSWhere/vswhere.exe.meta b/Editor/VSWhere/vswhere.exe.meta index 98d3694..3e707c0 100644 --- a/Editor/VSWhere/vswhere.exe.meta +++ b/Editor/VSWhere/vswhere.exe.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 585c3fb85b32bd64e8814074e754163e -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 585c3fb85b32bd64e8814074e754163e +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/VisualStudioEditor.cs b/Editor/VisualStudioEditor.cs new file mode 100644 index 0000000..44506c4 --- /dev/null +++ b/Editor/VisualStudioEditor.cs @@ -0,0 +1,258 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Unity Technologies. + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor; +using UnityEngine; +using Unity.CodeEditor; +using System.Runtime.InteropServices; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + [InitializeOnLoad] + public class VisualStudioEditor : IExternalCodeEditor + { + private static readonly VisualStudioInstallation[] _installations; + + internal static bool IsOSX => Application.platform == RuntimePlatform.OSXEditor; + internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n"; + + CodeEditor.Installation[] IExternalCodeEditor.Installations => _installations + .Select(i => i.ToCodeEditorInstallation()) + .ToArray(); + + private readonly IGenerator _generator = new ProjectGeneration(); + + static VisualStudioEditor() + { + try + { + _installations = Discovery + .GetVisualStudioInstallations() + .ToArray(); + } + catch (Exception ex) + { + UnityEngine.Debug.Log($"Error detecting Visual Studio installations: {ex}"); + _installations = Array.Empty(); + } + + CodeEditor.Register(new VisualStudioEditor()); + } + + public void CreateIfDoesntExist() + { + if (!_generator.HasSolutionBeenGenerated()) + _generator.Sync(); + } + + public void Initialize(string editorInstallationPath) + { + } + + internal bool TryGetVisualStudioInstallationForPath(string editorPath, out VisualStudioInstallation installation) + { + // lookup for well known installations + foreach (var candidate in _installations) + { + if (!string.Equals(Path.GetFullPath(editorPath), Path.GetFullPath(candidate.Path), StringComparison.OrdinalIgnoreCase)) + continue; + + installation = candidate; + return true; + } + + return Discovery.TryDiscoverInstallation(editorPath, out installation); + } + + public bool TryGetInstallationForPath(string editorPath, out CodeEditor.Installation installation) + { + var result = TryGetVisualStudioInstallationForPath(editorPath, out var vsi); + installation = vsi == null ? default : vsi.ToCodeEditorInstallation(); + return result; + } + + public void OnGUI() + { + const string unity_generate_all = "unity_generate_all_csproj"; + + GUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + + var package = UnityEditor.PackageManager.PackageInfo.FindForAssembly(GetType().Assembly); + + var style = new GUIStyle + { + richText = true, + margin = new RectOffset(0, 4, 0, 0) + }; + + GUILayout.Label($"{package.displayName} v{package.version} enabled", style); + GUILayout.EndHorizontal(); + + var prevGenerate = EditorPrefs.GetBool(unity_generate_all, false); + var generateAll = EditorGUILayout.Toggle("Generate all .csproj files.", prevGenerate); + if (generateAll != prevGenerate) + { + EditorPrefs.SetBool(unity_generate_all, generateAll); + } + + _generator.GenerateAll(generateAll); + } + + public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles) + { + _generator.SyncIfNeeded(addedFiles.Union(deletedFiles).Union(movedFiles).Union(movedFromFiles), importedFiles); + + foreach (var file in importedFiles.Where(a => Path.GetExtension(a) == ".pdb")) + { + var pdbFile = FileUtility.GetAssetFullPath(file); + if (Symbols.IsPortableSymbolFile(pdbFile)) + continue; + + UnityEngine.Debug.LogWarning($"Unity is only able to load mdb or portable-pdb symbols. {file} is using a legacy pdb format."); + } + } + + public void SyncAll() + { + AssetDatabase.Refresh(); + _generator.Sync(); + } + + bool IsSupportedPath(string path) + { + // Path is empty with "Open C# Project", as we only want to open the solution without specific files + if (string.IsNullOrEmpty(path)) + return true; + + // cs, uxml, uss, shader, compute, cginc, hlsl, glslinc, template are part of Unity builtin extensions + // txt, xml, fnt, cd are -often- par of Unity user extensions + // asdmdef is mandatory included + if (_generator.IsSupportedFile(path)) + return true; + + return false; + } + + public bool OpenProject(string path, int line, int column) + { + if (!IsSupportedPath(path)) + return false; + + if (IsOSX) + return OpenOSXApp(path, line, column); + + if (IsWindows) + return OpenWindowsApp(path, line); + + return false; + } + + private bool OpenWindowsApp(string path, int line) + { + var progpath = FileUtility + .FindPackageAssetFullPath("COMIntegration a:packages", "COMIntegration.exe") + .FirstOrDefault(); + + if (string.IsNullOrWhiteSpace(progpath)) + return false; + + string absolutePath = ""; + if (!string.IsNullOrWhiteSpace(path)) + { + absolutePath = Path.GetFullPath(path); + } + + // We remove all invalid chars from the solution filename, but we cannot prevent the user from using a specific path for the Unity project + // So process the fullpath to make it compatible with VS + var solution = GetOrGenerateSolutionFile(path); + if (!string.IsNullOrWhiteSpace(solution)) + { + solution = $"\"{solution}\""; + solution = solution.Replace("^", "^^"); + } + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = progpath, + Arguments = $"\"{CodeEditor.CurrentEditorInstallation}\" \"{absolutePath}\" {solution} {line}", + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + } + }; + var result = process.Start(); + + while (!process.StandardOutput.EndOfStream) + { + var outputLine = process.StandardOutput.ReadLine(); + if (outputLine == "displayProgressBar") + { + EditorUtility.DisplayProgressBar("Opening Visual Studio", "Starting up Visual Studio, this might take some time.", .5f); + } + + if (outputLine == "clearprogressbar") + { + EditorUtility.ClearProgressBar(); + } + } + + var errorOutput = process.StandardError.ReadToEnd(); + if (!string.IsNullOrEmpty(errorOutput)) + { + Console.WriteLine("Error: \n" + errorOutput); + } + + process.WaitForExit(); + return result; + } + + [DllImport("AppleEventIntegration")] + static extern bool OpenVisualStudio(string appPath, string solutionPath, string filePath, int line); + + bool OpenOSXApp(string path, int line, int column) + { + string absolutePath = ""; + if (!string.IsNullOrWhiteSpace(path)) + { + absolutePath = Path.GetFullPath(path); + } + + string solution = GetOrGenerateSolutionFile(path); + return OpenVisualStudio(CodeEditor.CurrentEditorInstallation, solution, absolutePath, line); + } + + private string GetOrGenerateSolutionFile(string path) + { + var solution = GetSolutionFile(path); + if (solution == "") + { + _generator.Sync(); + solution = GetSolutionFile(path); + } + + return solution; + } + + string GetSolutionFile(string path) + { + var solutionFile = _generator.SolutionFile(); + if (File.Exists(solutionFile)) + { + return solutionFile; + } + + return ""; + } + } +} diff --git a/Editor/VSEditor.cs.meta b/Editor/VisualStudioEditor.cs.meta similarity index 95% rename from Editor/VSEditor.cs.meta rename to Editor/VisualStudioEditor.cs.meta index 9d8987f..bdf0360 100644 --- a/Editor/VSEditor.cs.meta +++ b/Editor/VisualStudioEditor.cs.meta @@ -1,11 +1,11 @@ -fileFormatVersion: 2 -guid: 0173aff8c07e06b42af07ebdd7f08032 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 0173aff8c07e06b42af07ebdd7f08032 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/VisualStudioInstallation.cs b/Editor/VisualStudioInstallation.cs new file mode 100644 index 0000000..45f900e --- /dev/null +++ b/Editor/VisualStudioInstallation.cs @@ -0,0 +1,126 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.IO; +using Microsoft.Win32; +using Unity.CodeEditor; +using IOPath = System.IO.Path; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + internal class VisualStudioInstallation + { + public string Name { get; set; } + public string Path { get; set; } + public Version Version { get; set; } + public bool IsPrerelease { get; set; } + + public bool SupportsAnalyzers + { + get + { + if (VisualStudioEditor.IsWindows) + return Version >= new Version(16, 3); + + if (VisualStudioEditor.IsOSX) + return Version >= new Version(8, 3); + + return false; + } + } + + private static string ReadRegistry(RegistryKey hive, string keyName, string valueName) + { + try + { + var unitykey = hive.OpenSubKey(keyName); + + var result = (string)unitykey?.GetValue(valueName); + return result; + } + catch (Exception) + { + return null; + } + } + + // We only use this to find analyzers, we do not need to load this assembly anymore + private string GetBridgeLocation() + { + if (VisualStudioEditor.IsWindows) + { + // Registry, using legacy bridge location + var keyName = $"Software\\Microsoft\\Microsoft Visual Studio {Version.Major}.0 Tools for Unity"; + const string valueName = "UnityExtensionPath"; + + var bridge = ReadRegistry(Registry.CurrentUser, keyName, valueName); + if (string.IsNullOrEmpty(bridge)) + bridge = ReadRegistry(Registry.LocalMachine, keyName, valueName); + + return bridge; + } + + if (VisualStudioEditor.IsOSX) + { + // Environment, useful when developing UnityVS for Mac + var bridge = Environment.GetEnvironmentVariable("VSTUM_BRIDGE"); + if (!string.IsNullOrEmpty(bridge) && File.Exists(bridge)) + return bridge; + + const string addinBridge = "Editor/SyntaxTree.VisualStudio.Unity.Bridge.dll"; + const string addinName = "MonoDevelop.Unity"; + + // user addins repository + var localAddins = IOPath.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.Personal), + $"Library/Application Support/VisualStudio/${Version.Major}.0" + "/LocalInstall/Addins"); + + // In the user addins repository, the addins are suffixed by their versions, like `MonoDevelop.Unity.1.0` + // When installing another local user addin, MD will remove files inside the folder + // So we browse all VSTUM addins, and return the one with a bridge, which is the one MD will load + if (Directory.Exists(localAddins)) + { + foreach (var folder in Directory.GetDirectories(localAddins, addinName + "*", SearchOption.TopDirectoryOnly)) + { + bridge = IOPath.Combine(folder, addinBridge); + if (File.Exists(bridge)) + return bridge; + } + } + + // Check in Visual Studio.app/ + // In that case the name of the addin is used + bridge = IOPath.Combine(Path, $"Contents/Resources/lib/monodevelop/AddIns/{addinName}/{addinBridge}"); + if (File.Exists(bridge)) + return bridge; + } + + return null; + } + + public string[] GetAnalyzers() + { + var bridge = GetBridgeLocation(); + + if (!string.IsNullOrEmpty(bridge)) + { + var baseLocation = IOPath.Combine(IOPath.GetDirectoryName(bridge), ".."); + var analyzerLocation = IOPath.GetFullPath(IOPath.Combine(baseLocation, "Analyzers")); + + if (Directory.Exists(analyzerLocation)) + return Directory.GetFiles(analyzerLocation, "*Analyzers.dll", SearchOption.AllDirectories); + } + + // Local assets + // return FileUtility.FindPackageAssetFullPath("Analyzers a:packages", ".Analyzers.dll"); + return Array.Empty(); + } + + public CodeEditor.Installation ToCodeEditorInstallation() + { + return new CodeEditor.Installation() { Name = Name, Path = Path }; + } + } +} diff --git a/Editor/VisualStudioInstallation.cs.meta b/Editor/VisualStudioInstallation.cs.meta new file mode 100644 index 0000000..b3aa988 --- /dev/null +++ b/Editor/VisualStudioInstallation.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb86eea06f54fb24caa7046a8a764945 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/VisualStudioIntegration.cs b/Editor/VisualStudioIntegration.cs new file mode 100644 index 0000000..e1c8873 --- /dev/null +++ b/Editor/VisualStudioIntegration.cs @@ -0,0 +1,174 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using Microsoft.Unity.VisualStudio.Editor.Messaging; +using UnityEditor; +using UnityEngine; +using MessageType = Microsoft.Unity.VisualStudio.Editor.Messaging.MessageType; + +namespace Microsoft.Unity.VisualStudio.Editor +{ + [InitializeOnLoad] + internal class VisualStudioIntegration + { + private static Messager _messager; + + private static readonly Queue Incoming = new Queue(); + private static readonly object IncomingLock = new object(); + + public static Application.LogCallback LogCallback = delegate { }; + + static VisualStudioIntegration() + { + RunOnceOnUpdate(() => + { + _messager = Messager.BindTo(MessagingPort()); + _messager.ReceiveMessage += ReceiveMessage; + + RunOnShutdown(Shutdown); + }); + + EditorApplication.update += OnUpdate; + } + + private static void RunOnceOnUpdate(Action action) + { + var callback = null as EditorApplication.CallbackFunction; + + callback = () => + { + EditorApplication.update -= callback; + action(); + }; + + EditorApplication.update += callback; + } + + private static void RunOnShutdown(Action action) + { + // Mono on OSX has all kinds of quirks on AppDomain shutdown + if (!VisualStudioEditor.IsWindows) + return; + + AppDomain.CurrentDomain.DomainUnload += (_, __) => action(); + } + + private static int DebuggingPort() + { + return 56000 + (System.Diagnostics.Process.GetCurrentProcess().Id % 1000); + } + + private static int MessagingPort() + { + return DebuggingPort() + 2; + } + + private static void ReceiveMessage(object sender, MessageEventArgs args) + { + OnMessage(args.Message); + } + + private static void OnUpdate() + { + lock (IncomingLock) + { + while (Incoming.Count > 0) + { + ProcessIncoming(Incoming.Dequeue()); + } + } + } + + private static void AddMessage(Message message) + { + lock (IncomingLock) + { + Incoming.Enqueue(message); + } + } + + private static void ProcessIncoming(Message message) + { + switch (message.Type) + { + case MessageType.Ping: + Answer(message, MessageType.Pong); + break; + case MessageType.Play: + Shutdown(); + EditorApplication.isPlaying = true; + break; + case MessageType.Stop: + EditorApplication.isPlaying = false; + break; + case MessageType.Pause: + EditorApplication.isPaused = true; + break; + case MessageType.Unpause: + EditorApplication.isPaused = false; + break; + case MessageType.Build: + // Not used anymore + break; + case MessageType.Refresh: + Refresh(); + break; + case MessageType.Version: + Answer(message, MessageType.Version, PackageVersion()); + break; + case MessageType.UpdatePackage: + // Not used anymore + break; + case MessageType.ProjectPath: + Answer(message, MessageType.ProjectPath, Path.GetFullPath(Path.Combine(Application.dataPath, ".."))); + break; + } + } + + private static string PackageVersion() + { + var package = UnityEditor.PackageManager.PackageInfo.FindForAssembly(typeof(VisualStudioIntegration).Assembly); + return package.version; + } + + private static void Refresh() + { + RunOnceOnUpdate(AssetDatabase.Refresh); + } + + private static void OnMessage(Message message) + { + AddMessage(message); + } + + private static void Answer(Message message, MessageType answerType, string answerValue = "") + { + var targetEndPoint = message.Origin; + + Answer( + targetEndPoint, + answerType, + answerValue); + } + + private static void Answer(IPEndPoint targetEndPoint, MessageType answerType, string answerValue) + { + _messager?.SendMessage(targetEndPoint, answerType, answerValue); + } + + private static void Shutdown() + { + if (_messager == null) + return; + + _messager.ReceiveMessage -= ReceiveMessage; + _messager.Dispose(); + _messager = null; + } + } +} diff --git a/Editor/VisualStudioIntegration.cs.meta b/Editor/VisualStudioIntegration.cs.meta new file mode 100644 index 0000000..30baf7c --- /dev/null +++ b/Editor/VisualStudioIntegration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 48fcd6ebd5ce8fd4cbe931895233677d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/com.unity.ide.visualstudio.asmdef b/Editor/com.unity.ide.visualstudio.asmdef index 5ad8d8e..6f75d98 100644 --- a/Editor/com.unity.ide.visualstudio.asmdef +++ b/Editor/com.unity.ide.visualstudio.asmdef @@ -1,9 +1,9 @@ -{ - "name": "Unity.VisualStudio.Editor", - "references": [], - "optionalUnityReferences": [], - "includePlatforms": [ - "Editor" - ], - "excludePlatforms": [] -} +{ + "name": "Unity.VisualStudio.Editor", + "references": [], + "optionalUnityReferences": [], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [] +} diff --git a/Editor/com.unity.ide.visualstudio.asmdef.meta b/Editor/com.unity.ide.visualstudio.asmdef.meta index 899f13c..0b1887f 100644 --- a/Editor/com.unity.ide.visualstudio.asmdef.meta +++ b/Editor/com.unity.ide.visualstudio.asmdef.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: b93f844d45cfcc44fa2b0eed5c9ec6bb -AssemblyDefinitionImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: b93f844d45cfcc44fa2b0eed5c9ec6bb +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/LICENSE.md b/LICENSE.md index 8098f2d..c4c4725 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,21 +1,22 @@ -MIT License - -Copyright (c) 2019 Unity Technologies - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2019 Unity Technologies +Copyright (c) 2019 Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSE.md.meta b/LICENSE.md.meta index df06dd0..eb7cb2a 100644 --- a/LICENSE.md.meta +++ b/LICENSE.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 1fe9e6e1ae93cf64bbdfbd29300752e1 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 1fe9e6e1ae93cf64bbdfbd29300752e1 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ThirdPartyNotices.md b/ThirdPartyNotices.md index e03e636..fa8f45d 100644 --- a/ThirdPartyNotices.md +++ b/ThirdPartyNotices.md @@ -1,31 +1,31 @@ -This package contains third-party software components governed by the license(s) indicated below: ---------- - -Component Name: VSWhere - -License Type: "MIT" - -The MIT License (MIT) -Copyright (C) Microsoft Corporation. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ---------- -Component Name: benbuck/EnvDTE - -License Type: Zero-Clause BSD - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +This package contains third-party software components governed by the license(s) indicated below: +--------- + +Component Name: VSWhere + +License Type: "MIT" + +The MIT License (MIT) +Copyright (C) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--------- +Component Name: benbuck/EnvDTE + +License Type: Zero-Clause BSD + +Permission to use, copy, modify, and/or distribute this software for any purpose +with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. \ No newline at end of file diff --git a/ThirdPartyNotices.md.meta b/ThirdPartyNotices.md.meta index e7f61ce..c61f73b 100644 --- a/ThirdPartyNotices.md.meta +++ b/ThirdPartyNotices.md.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 7809f42f64c877f4b90ac233e5ec2372 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 7809f42f64c877f4b90ac233e5ec2372 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/package.json b/package.json index 22fcd54..a22ff54 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,16 @@ "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": "1.0.11", - "unity": "2019.2", + "version": "2.0.0", + "unity": "2020.1", "unityRelease": "0a12", "dependencies": {}, "relatedPackages": { - "com.unity.ide.visualstudio.tests": "1.0.5" + "com.unity.ide.visualstudio.tests": "2.0.0" }, "repository": { "type": "git", "url": "git@github.cds.internal.unity3d.com:unity/com.unity.ide.visualstudio.git", - "revision": "7378597cbd075d617aade65f1aa9c13a22c00d1c" + "revision": "a3fbcc6d9504b41b441ecf6caeb3bbc753d6d010" } } diff --git a/package.json.meta b/package.json.meta index ed41749..d0c5459 100644 --- a/package.json.meta +++ b/package.json.meta @@ -1,7 +1,7 @@ -fileFormatVersion: 2 -guid: 656f74f6edaa396458412b9e3903d8cd -PackageManifestImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: +fileFormatVersion: 2 +guid: 656f74f6edaa396458412b9e3903d8cd +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: