From 4494f57bd058a2b5c3b364ac76d0d2f9ec379eb9 Mon Sep 17 00:00:00 2001 From: Unity Technologies <@unity> Date: Tue, 5 Mar 2019 00:00:00 +0000 Subject: [PATCH] com.unity.ide.visualstudio@1.0.9 ## [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. --- CHANGELOG.md | 19 + .../COMIntegration/Debug/COMIntegration.exe | Bin 186880 -> 0 bytes .../{Debug.meta => Release.meta} | 0 Editor/Discovery.cs | 240 ++++++++++++- Editor/Plugins.meta | 8 + .../AppleEventIntegrationPlugin.bundle.meta | 28 ++ .../Contents.meta | 8 + .../Contents/Info.plist | 44 +++ .../Contents/Info.plist.meta} | 2 +- .../Contents/MacOS.meta | 8 + .../MacOS/AppleEventIntegrationPlugin | Bin 0 -> 34976 bytes .../MacOS/AppleEventIntegrationPlugin.meta | 7 + .../Contents/_CodeSignature.meta | 8 + .../Contents/_CodeSignature/CodeResources | 115 ++++++ .../_CodeSignature/CodeResources.meta | 7 + Editor/ProjectGeneration.cs | 59 +++- Editor/VSEditor.cs | 334 ++++++------------ package.json | 8 +- 18 files changed, 641 insertions(+), 254 deletions(-) delete mode 100644 Editor/COMIntegration/Debug/COMIntegration.exe rename Editor/COMIntegration/{Debug.meta => Release.meta} (100%) create mode 100644 Editor/Plugins.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist rename Editor/{COMIntegration/Debug/COMIntegration.exe.meta => Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta} (71%) create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature.meta create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources create mode 100644 Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta diff --git a/CHANGELOG.md b/CHANGELOG.md index a6f0afb..0751020 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Code Editor Package for Visual Studio +## [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. diff --git a/Editor/COMIntegration/Debug/COMIntegration.exe b/Editor/COMIntegration/Debug/COMIntegration.exe deleted file mode 100644 index a77822e767a0a3accd396c8d299118ada77e3fa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 186880 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 diff --git a/Editor/COMIntegration/Debug.meta b/Editor/COMIntegration/Release.meta similarity index 100% rename from Editor/COMIntegration/Debug.meta rename to Editor/COMIntegration/Release.meta diff --git a/Editor/Discovery.cs b/Editor/Discovery.cs index 8c6e46a..7a0c5b9 100644 --- a/Editor/Discovery.cs +++ b/Editor/Discovery.cs @@ -1,7 +1,12 @@ using System; +using System.IO; +using System.Collections.Generic; using System.Linq; using Unity.CodeEditor; using UnityEngine; +using UnityEditor; +using System.Diagnostics; +using Microsoft.Win32; namespace VisualStudioEditor { @@ -31,16 +36,239 @@ namespace VisualStudioEditor { try { - return VSEditor.GetInstalledVisualStudios().Select(pair => new CodeEditor.Installation + if (VSEditor.IsWindows) { - Path = pair.Value[0], - Name = VisualStudioVersionToNiceName(pair.Key) - }).ToArray(); + return GetInstalledVisualStudios().Select(pair => 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) { - Debug.Log($"Error detecting Visual Studio installations: {ex.Message}{Environment.NewLine}{ex.StackTrace}"); - return new CodeEditor.Installation[0]; + 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(); } } } diff --git a/Editor/Plugins.meta b/Editor/Plugins.meta new file mode 100644 index 0000000..6e01768 --- /dev/null +++ b/Editor/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1e5abb64fdd0542b38f4dc1b60343e8a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta b/Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta new file mode 100644 index 0000000..991b7e7 --- /dev/null +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle.meta @@ -0,0 +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: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta new file mode 100644 index 0000000..1eeb0e2 --- /dev/null +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 179209ff257e808409c755d32ecf1086 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist new file mode 100644 index 0000000..50c0c33 --- /dev/null +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist @@ -0,0 +1,44 @@ + + + + + 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. + + diff --git a/Editor/COMIntegration/Debug/COMIntegration.exe.meta b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta similarity index 71% rename from Editor/COMIntegration/Debug/COMIntegration.exe.meta rename to Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta index e927985..4d47fc5 100644 --- a/Editor/COMIntegration/Debug/COMIntegration.exe.meta +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/Info.plist.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: cb67edc1800c2ec4ba8dfb1cf0dfc84a +guid: d2694cce95579ec47a939a1a3efb8f33 DefaultImporter: externalObjects: {} userData: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta new file mode 100644 index 0000000..773ad15 --- /dev/null +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a0f0c231a0e381e4ea37a97a8e7837a0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/MacOS/AppleEventIntegrationPlugin new file mode 100644 index 0000000000000000000000000000000000000000..3f59902e9be802fffc7589ed1ce228ec604cc4bf GIT binary patch literal 34976 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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 new file mode 100644 index 0000000..7968517 --- /dev/null +++ b/Editor/Plugins/AppleEventIntegrationPlugin.bundle/Contents/_CodeSignature/CodeResources.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8529f5a60acb8cd4395bd1cec74495ae +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Editor/ProjectGeneration.cs b/Editor/ProjectGeneration.cs index 5a2a10e..e50aadc 100644 --- a/Editor/ProjectGeneration.cs +++ b/Editor/ProjectGeneration.cs @@ -22,6 +22,7 @@ namespace VisualStudioEditor bool HasSolutionBeenGenerated(); string SolutionFile(); string ProjectDirectory { get; } + void GenerateAll(bool generateAll); } public interface IAssemblyNameProvider @@ -29,6 +30,12 @@ namespace VisualStudioEditor 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 @@ -47,6 +54,11 @@ namespace VisualStudioEditor { return AssetDatabase.GetAllAssetPaths(); } + + public UnityEditor.PackageManager.PackageInfo FindForAssetPath(string assetPath) + { + return UnityEditor.PackageManager.PackageInfo.FindForAssetPath(assetPath); + } } public class ProjectGeneration : IGenerator @@ -94,26 +106,32 @@ namespace VisualStudioEditor 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() + public ProjectGeneration() : this(Directory.GetParent(Application.dataPath).FullName, new AssemblyNameProvider()) { - var projectDirectory = Directory.GetParent(Application.dataPath).FullName; - ProjectDirectory = projectDirectory.Replace('\\', '/'); - m_ProjectName = Path.GetFileName(ProjectDirectory); - m_AssemblyNameProvider = 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. /// @@ -176,7 +194,7 @@ namespace VisualStudioEditor string extension = Path.GetExtension(file); // Exclude files coming from packages except if they are internalized. - if (IsInternalizedPackagePath(file)) + if (!m_ShouldGenerateAll && IsInternalizedPackagePath(file)) { return false; } @@ -296,7 +314,7 @@ namespace VisualStudioEditor foreach (string asset in m_AssemblyNameProvider.GetAllAssetPaths()) { // Exclude files coming from packages except if they are internalized. - if (IsInternalizedPackagePath(asset)) + if (!m_ShouldGenerateAll && IsInternalizedPackagePath(asset)) { continue; } @@ -306,8 +324,6 @@ namespace VisualStudioEditor { // Find assembly the asset belongs to by adding script extension and using compilation pipeline. var assemblyName = m_AssemblyNameProvider.GetAssemblyNameFromScriptPath(asset + ".cs"); - assemblyName = assemblyName ?? m_AssemblyNameProvider.GetAssemblyNameFromScriptPath(asset + ".js"); - assemblyName = assemblyName ?? m_AssemblyNameProvider.GetAssemblyNameFromScriptPath(asset + ".boo"); if (string.IsNullOrEmpty(assemblyName)) { @@ -334,14 +350,14 @@ namespace VisualStudioEditor return result; } - static bool IsInternalizedPackagePath(string file) + bool IsInternalizedPackagePath(string file) { if (string.IsNullOrWhiteSpace(file)) { return false; } - var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(file); + var packageInfo = m_AssemblyNameProvider.FindForAssetPath(file); if (packageInfo == null) { return false; } @@ -358,7 +374,7 @@ namespace VisualStudioEditor SyncProjectFileIfNotChanged(ProjectFile(island), ProjectText(island, allAssetsProjectParts, responseFilesData, allProjectIslands)); } - static void SyncProjectFileIfNotChanged(string path, string newContents) + void SyncProjectFileIfNotChanged(string path, string newContents) { if (Path.GetExtension(path) == ".csproj") { @@ -368,7 +384,7 @@ namespace VisualStudioEditor SyncFileIfNotChanged(path, newContents); } - static void SyncSolutionFileIfNotChanged(string path, string newContents) + void SyncSolutionFileIfNotChanged(string path, string newContents) { newContents = OnGeneratedSlnSolution(path, newContents); @@ -455,7 +471,7 @@ namespace VisualStudioEditor return content; } - static void SyncFileIfNotChanged(string filename, string newContents) + void SyncFileIfNotChanged(string filename, string newContents) { if (File.Exists(filename) && newContents == File.ReadAllText(filename)) @@ -463,7 +479,16 @@ namespace VisualStudioEditor return; } - File.WriteAllText(filename, newContents, Encoding.UTF8); + 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, @@ -779,7 +804,7 @@ namespace VisualStudioEditor file = file.Replace('/', '\\'); var path = SkipPathPrefix(file, projectDir); - var packageInfo = UnityEditor.PackageManager.PackageInfo.FindForAssetPath(path.Replace('\\', '/')); + 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. @@ -792,7 +817,7 @@ namespace VisualStudioEditor static string SkipPathPrefix(string path, string prefix) { - if (path.StartsWith(prefix)) + if (path.Replace("\\","/").StartsWith($"{prefix}/")) return path.Substring(prefix.Length + 1); return path; } diff --git a/Editor/VSEditor.cs b/Editor/VSEditor.cs index 4246da5..598c20a 100644 --- a/Editor/VSEditor.cs +++ b/Editor/VSEditor.cs @@ -3,11 +3,14 @@ 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 { @@ -32,42 +35,11 @@ namespace VisualStudioEditor "\n(This does work with Visual Studio Pro)" ); - 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(); - } - } - static VSEditor() { try { - InstalledVisualStudios = GetInstalledVisualStudios(); + InstalledVisualStudios = Discovery.GetInstalledVisualStudios(); } catch (Exception ex) { @@ -79,16 +51,19 @@ namespace VisualStudioEditor var current = CodeEditor.CurrentEditorInstallation; if (editor.TryGetInstallationForPath(current, out var installation)) { - editor.Initialize(current); + 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_Initiliazer = new VSInitializer(); - bool m_ExternalEditorSupportsUnityProj; + VSInitializer m_Initializer = new VSInitializer(); public VSEditor(IDiscovery discovery, IGenerator projectGeneration) { @@ -98,186 +73,11 @@ namespace VisualStudioEditor internal static Dictionary InstalledVisualStudios { get; private set; } - static bool IsOSX => Environment.OSVersion.Platform == PlatformID.Unix; - static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n"; - static readonly GUIContent k_AddUnityProjeToSln = EditorGUIUtility.TrTextContent("Add .unityproj's to .sln"); - - 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"; - } + internal static bool IsOSX => Environment.OSVersion.Platform == PlatformID.Unix; + internal static bool IsWindows => !IsOSX && Path.DirectorySeparatorChar == '\\' && Environment.NewLine == "\r\n"; public CodeEditor.Installation[] Installations => m_Discoverability.PathCallback(); - 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 - /// - internal static Dictionary GetInstalledVisualStudios() - { - var versions = new Dictionary(); - - if (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) }; - } - } - public void CreateIfDoesntExist() { if (!m_Generation.HasSolutionBeenGenerated()) @@ -338,12 +138,13 @@ namespace VisualStudioEditor GUILayout.EndHorizontal(); } - if (m_Installation.Name.Equals("MonoDevelop")) + var prevGenerate = EditorPrefs.GetBool(unity_generate_all, false); + var generateAll = EditorGUILayout.Toggle("Generate all .csproj files.", prevGenerate); + if (generateAll != prevGenerate) { - m_ExternalEditorSupportsUnityProj = EditorGUILayout.Toggle( - k_AddUnityProjeToSln, - m_ExternalEditorSupportsUnityProj); + EditorPrefs.SetBool(unity_generate_all, generateAll); } + m_Generation.GenerateAll(generateAll); } public void SyncIfNeeded(string[] addedFiles, string[] deletedFiles, string[] movedFiles, string[] movedFromFiles, string[] importedFiles) @@ -353,17 +154,37 @@ namespace VisualStudioEditor public void SyncAll() { + AssetDatabase.Refresh(); m_Generation.Sync(); } public void Initialize(string editorInstallationPath) { - m_Initiliazer.Initialize(editorInstallationPath, InstalledVisualStudios); + m_Initializer.Initialize(editorInstallationPath, InstalledVisualStudios); } public bool OpenProject(string path, int line, int column) { - var comAssetPath = AssetDatabase.FindAssets("COMIntegration a:packages").Select(AssetDatabase.GUIDToAssetPath).First(assetPath => assetPath.Contains("COMIntegration.exe")); + 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; @@ -376,12 +197,8 @@ namespace VisualStudioEditor absolutePath = Path.GetFullPath(path); } - var solution = GetSolutionFile(path); - if (solution == "") - { - m_Generation.Sync(); - solution = GetSolutionFile(path); - } + + var solution = GetOrGenerateSolutionFile(path); solution = solution == "" ? "" : $"\"{solution}\""; var process = new Process { @@ -420,7 +237,72 @@ namespace VisualStudioEditor return result; } - private string GetSolutionFile(string path) + 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()) { @@ -443,7 +325,7 @@ namespace VisualStudioEditor return ""; } - private static string GetBaseUnityDeveloperFolder() + static string GetBaseUnityDeveloperFolder() { return Directory.GetParent(EditorApplication.applicationPath).Parent.Parent.FullName; } diff --git a/package.json b/package.json index 935fda8..466c688 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.4", + "version": "1.0.9", "unity": "2019.2", - "unityRelease": "0a7", + "unityRelease": "0a12", "dependencies": {}, "relatedPackages": { - "com.unity.ide.visualstudio.tests": "1.0.2" + "com.unity.ide.visualstudio.tests": "1.0.5" }, "repository": { "type": "git", "url": "git@github.cds.internal.unity3d.com:unity/com.unity.ide.visualstudio.git", - "revision": "89fbb2a14dd60b56c2eb64eac1e574a40a105822" + "revision": "e7d6cf461bbe2604836a0e783a1992651c28c535" } }