Example #1
0
        // this method should be very fast as it gets called a lot
        public HostProviderAvailability GetAvailability(IUnitTestElement element)
        {
            var solution = element.Id.Project.GetSolution();
            var tracker  = solution.GetComponent <UnitySolutionTracker>();

            if (tracker.IsUnityProject.HasValue() && !tracker.IsUnityProject.Value)
            {
                return(HostProviderAvailability.Available);
            }

            var frontendBackendModel = solution.GetProtocolSolution().GetFrontendBackendModel();

            switch (frontendBackendModel.UnitTestPreference.Value)
            {
            case UnitTestLaunchPreference.NUnit:
                return(HostProviderAvailability.Available);

            case UnitTestLaunchPreference.Both:
            case UnitTestLaunchPreference.PlayMode:
            case UnitTestLaunchPreference.EditMode:
            {
                var unityVersion = UnityVersion.Parse(frontendBackendModel.UnityApplicationData.Maybe.ValueOrDefault?.ApplicationVersion ?? string.Empty);

                return(unityVersion == null || unityVersion < ourMinSupportedUnityVersion
                        ? HostProviderAvailability.Nonexistent
                        : HostProviderAvailability.Available);
            }

            default:
                return(HostProviderAvailability.Nonexistent);
            }
        }
        public static UnityPluginParameter ParseUnityPluginParameter(
            Configs.UnityPlugins configs, Configs.UnityManagedPluginProject projectConfig)
        {
            Ensure.Argument.NotNull(configs, nameof(configs));
            Ensure.Argument.NotNull(projectConfig, nameof(projectConfig));

            StringToVersionInfo versions = null;

            if (projectConfig.ForMultipleVersions)
            {
                versions = projectConfig.Versions ?? new StringToVersionInfo();
                foreach (var kvp in configs.DefaultVersions)
                {
                    var ver  = kvp.Key;
                    var info = kvp.Value;
                    if (!versions.ContainsKey(ver))
                    {
                        versions.Add(ver, info);
                    }
                }
            }

            var parameter = new UnityPluginParameter
            {
                ForEditor = projectConfig.ForEditor,
                Versions  = versions?.ToDictionary(p => UnityVersion.Parse(p.Key), p => p.Value)
            };

            return(parameter);
        }
        private async Task RefreshInternal(Lifetime lifetime, RefreshType refreshType)
        {
            var lifetimeDef = Lifetime.Define(lifetime);

            myLogger.Verbose($"myPluginProtocolController.UnityModel.Value.Refresh.StartAsTask, force = {refreshType} Started");
            mySolution.GetComponent <RiderBackgroundTaskHost>().AddNewTask(lifetimeDef.Lifetime,
                                                                           RiderBackgroundTaskBuilder.Create().WithHeader("Refreshing solution in Unity Editor...")
                                                                           .AsIndeterminate().AsNonCancelable());
            try
            {
                try
                {
                    var version = UnityVersion.Parse(myEditorProtocol.UnityModel.Value.UnityApplicationData.Value.ApplicationVersion);
                    if (version != null && version.Major < 2018)
                    {
                        using (mySolution.GetComponent <VfsListener>().PauseChanges())
                        {
                            await myEditorProtocol.UnityModel.Value.Refresh.Start(lifetimeDef.Lifetime, refreshType).AsTask();
                        }
                    }
                    else // it is a risk to pause vfs https://github.com/JetBrains/resharper-unity/issues/1601
                    {
                        await myEditorProtocol.UnityModel.Value.Refresh.Start(lifetimeDef.Lifetime, refreshType).AsTask();
                    }
                }
                catch (Exception e)
                {
                    myLogger.Warn("connection usually brakes during refresh.", e);
                }
                finally
                {
                    try
                    {
                        myLogger.Verbose(
                            $"myPluginProtocolController.UnityModel.Value.Refresh.StartAsTask, force = {refreshType} Finished");
                        var solution  = mySolution.GetProtocolSolution();
                        var solFolder = mySolution.SolutionDirectory;
                        var list      = new List <string> {
                            solFolder.FullPath
                        };
                        myLogger.Verbose($"RefreshPaths.StartAsTask Finished.");
                        await solution.GetFileSystemModel().RefreshPaths.Start(lifetimeDef.Lifetime, new RdRefreshRequest(list, true)).AsTask();
                    }
                    finally
                    {
                        myLogger.Verbose($"RefreshPaths.StartAsTask Finished.");
                        lifetimeDef.Terminate();
                    }
                }
            }
            catch (Exception e)
            {
                myLogger.LogException(e);
            }
            finally
            {
                lifetimeDef.Terminate();
            }
        }
        internal static bool UnityVersionSatisfiesPackageUnityVersion(string unityVersionString, string packageUnityVersionString)
        {
            var unityVersion        = UnityVersion.Parse(unityVersionString);
            var packageUnityVersion = UnityVersion.Parse(packageUnityVersionString);

            // We only care about major and minor version
            var truncatedUnityVersion        = new SemVersion(unityVersion.Major, unityVersion.Minor);
            var truncatedPackageUnityVersion = new SemVersion(packageUnityVersion.Major, packageUnityVersion.Minor);

            return(truncatedUnityVersion >= truncatedPackageUnityVersion);
        }
        private static Version TryGetUnityVersionFromDll(XmlElement documentElement)
        {
            var referencePathElement = documentElement.ChildElements()
                                       .Where(a => a.Name == "ItemGroup").SelectMany(b => b.ChildElements())
                                       .Where(c => c.Name == "Reference" && c.GetAttribute("Include").StartsWith("UnityEngine") || c.GetAttribute("Include").Equals("UnityEditor"))
                                       .SelectMany(d => d.ChildElements())
                                       .FirstOrDefault(c => c.Name == "HintPath");

            if (referencePathElement == null || string.IsNullOrEmpty(referencePathElement.InnerText))
            {
                return(null);
            }

            var filePath = FileSystemPath.Parse(referencePathElement.InnerText);

            if (!filePath.IsAbsolute) // RIDER-21237
            {
                return(null);
            }

            if (filePath.ExistsFile)
            {
                if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.Windows)
                {
                    var exePath = filePath.Combine("../../../Unity.exe"); // Editor\Data\Managed\UnityEngine.dll
                    if (!exePath.ExistsFile)
                    {
                        exePath = filePath.Combine("../../../../Unity.exe"); // Editor\Data\Managed\UnityEngine\UnityEngine.dll
                    }
                    if (exePath.ExistsFile)
                    {
                        return(new Version(new Version(FileVersionInfo.GetVersionInfo(exePath.FullPath).FileVersion).ToString(3)));
                    }
                }
                else if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.MacOsX)
                {
                    var infoPlistPath = filePath.Combine("../../Info.plist");
                    if (!infoPlistPath.ExistsFile)
                    {
                        infoPlistPath = filePath.Combine("../../../Info.plist");
                    }
                    if (!infoPlistPath.ExistsFile)
                    {
                        return(null);
                    }
                    var fullVersion = UnityVersion.GetVersionFromInfoPlist(infoPlistPath);
                    return(UnityVersion.Parse(fullVersion));
                }
            }

            return(null);
        }
        private static UnityVersion FindProjectVersion(DirectoryInfo unityProjectDir)
        {
            var versionPath = Path.Combine(unityProjectDir.FullName, "ProjectSettings", "ProjectVersion.txt");
            var versionText = File.ReadAllText(versionPath);

            var match = UnityVersionRegex.Match(versionText);

            if (!match.Success)
            {
                throw new ConfigParseException("Failed to parse unity version from ProjectVersion.txt.");
            }

            var ver = match.Groups["ver"].Value;

            return(UnityVersion.Parse(ver));
        }
        private static UnityVersion ParseVersion()
        {
            var versionPath = Path.Combine(ProjectPaths.Settings, "ProjectVersion.txt");
            var versionText = File.ReadAllText(versionPath);

            var match = VersionRegex.Match(versionText);

            if (!match.Success)
            {
                throw new InvalidOperationException("Failed to parse unity version from ProjectVersion.txt.");
            }

            var ver = match.Groups["ver"].Value;

            return(UnityVersion.Parse(ver));
        }
 private void TrackActivity(BackendUnityModel backendUnityModel, Lifetime modelLifetime)
 {
     backendUnityModel.UnityApplicationData.AdviseOnce(modelLifetime, data =>
     {
         // ApplicationVersion may look like `2017.2.1f1-CustomPostfix`
         var unityVersion = UnityVersion.VersionToString(UnityVersion.Parse(data.ApplicationVersion));
         if (data.ApplicationVersion.StartsWith(unityVersion) && unityVersion != data.ApplicationVersion)
         {
             myUsageStatistics.TrackActivity("UnityVersion", unityVersion + "-custom"); // impersonate, but still track that it is custom build
         }
         else
         {
             myUsageStatistics.TrackActivity("UnityVersion", unityVersion);
         }
     });
     backendUnityModel.UnityProjectSettings.ScriptingRuntime.AdviseOnce(modelLifetime, runtime =>
     {
         myUsageStatistics.TrackActivity("ScriptingRuntime", runtime.ToString());
     });
 }
        protected override UnityVersion DetermineVersion(FilePath editorPath)
        {
            log.Debug($"Determining version of Unity Editor at path {editorPath}...");

            string version;

            using (var stream = fileSystem.GetFile(PlistPath(editorPath)).OpenRead())
                version = new InfoPlistParser().UnityVersionFromInfoPlist(stream);

            if (version == null)
            {
                log.Debug($"Can't find UnityVersion for {editorPath}");
                return(null);
            }

            var unityVersion = UnityVersion.Parse(version);

            log.Debug($"Result Unity Editor version (full): {unityVersion}");
            return(unityVersion);
        }
        private void CreateProtocols(FileSystemPath protocolInstancePath)
        {
            if (!protocolInstancePath.ExistsFile)
            {
                return;
            }

            List <ProtocolInstance> protocolInstanceList;

            try
            {
                protocolInstanceList = ProtocolInstance.FromJson(protocolInstancePath.ReadAllText2().Text);
            }
            catch (Exception e)
            {
                myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e);
                return;
            }

            var protocolInstance = protocolInstanceList?.SingleOrDefault(a => a.SolutionName == mySolution.SolutionFilePath.NameWithoutExtension);

            if (protocolInstance == null)
            {
                return;
            }

            myLogger.Info($"EditorPlugin protocol port {protocolInstance.Port} for Solution: {protocolInstance.SolutionName}.");

            try
            {
                var lifetime = mySessionLifetimes.Next();
                myLogger.Info("Create protocol...");

                myLogger.Info("Creating SocketWire with port = {0}", protocolInstance.Port);
                var wire = new SocketWire.Client(lifetime, myDispatcher, protocolInstance.Port, "UnityClient");

                var protocol = new Protocol("UnityEditorPlugin", new Serializers(),
                                            new Identities(IdKind.Client), myDispatcher, wire, lifetime);

                protocol.ThrowErrorOnOutOfSyncModels = false;

                protocol.OutOfSyncModels.AdviseOnce(lifetime, e =>
                {
                    if (myPluginInstallations.Contains(mySolution.SolutionFilePath))
                    {
                        return;
                    }

                    myPluginInstallations.Add(mySolution.SolutionFilePath); // avoid displaying Notification multiple times on each AppDomain.Reload in Unity

                    var appVersion = myUnityVersion.GetActualVersionForSolution();
                    if (appVersion < new Version(2019, 2))
                    {
                        var entry     = myBoundSettingsStore.Schema.GetScalarEntry((UnitySettings s) => s.InstallUnity3DRiderPlugin);
                        var isEnabled = myBoundSettingsStore.GetValueProperty <bool>(lifetime, entry, null).Value;
                        if (!isEnabled)
                        {
                            myHost.PerformModelAction(model => model.OnEditorModelOutOfSync());
                        }
                    }
                    else
                    {
                        var notification = new NotificationModel("Advanced Unity integration is unavailable",
                                                                 $"Please update External Editor to {myHostProductInfo.VersionMarketingString} in Unity Preferences.",
                                                                 true, RdNotificationEntryType.WARN);
                        mySolution.Locks.ExecuteOrQueue(lifetime, "OutOfSyncModels.Notify", () => myNotificationsModel.Notification(notification));
                    }
                });

                wire.Connected.WhenTrue(lifetime, lf =>
                {
                    myLogger.Info("WireConnected.");

                    var editor = new EditorPluginModel(lf, protocol);
                    editor.IsBackendConnected.Set(rdVoid => true);

                    if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.Windows)
                    {
                        var frontendProcess = Process.GetCurrentProcess().GetParent(); // RiderProcessId is not used on non-Windows, but this line gives bad warning in the log
                        if (frontendProcess != null)
                        {
                            editor.RiderProcessId.SetValue(frontendProcess.Id);
                        }
                    }

                    myHost.PerformModelAction(m => m.SessionInitialized.Value = true);

                    SubscribeToLogs(lf, editor);
                    SubscribeToOpenFile(editor);

                    editor.Play.Advise(lf, b => myHost.PerformModelAction(rd => rd.Play.SetValue(b)));
                    editor.Pause.Advise(lf, b => myHost.PerformModelAction(rd => rd.Pause.SetValue(b)));
                    editor.ClearOnPlay.Advise(lf, time => myHost.PerformModelAction(rd => rd.ClearOnPlay(time)));

                    editor.UnityProcessId.View(lf, (_, pid) => myHost.PerformModelAction(t => t.UnityProcessId.Set(pid)));

                    // I have split this into groups, because want to use async api for finding reference and pass them via groups to Unity
                    myHost.PerformModelAction(t => t.ShowFileInUnity.Advise(lf, v => editor.ShowFileInUnity.Fire(v)));
                    myHost.PerformModelAction(t => t.ShowPreferences.Advise(lf, v =>
                    {
                        editor.ShowPreferences.Fire();
                    }));

                    editor.EditorLogPath.Advise(lifetime,
                                                s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s)));
                    editor.PlayerLogPath.Advise(lifetime,
                                                s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s)));

                    // Note that these are late-init properties. Once set, they are always set and do not allow nulls.
                    // This means that if/when the Unity <-> Backend protocol closes, they still retain the last value
                    // they had - so the front end will retain the log and application paths of the just-closed editor.
                    // Opening a new editor instance will reconnect and push a new value through to the front end
                    editor.UnityApplicationData.Advise(lifetime,
                                                       s => myHost.PerformModelAction(a =>
                    {
                        var version = UnityVersion.Parse(s.ApplicationVersion);
                        a.UnityApplicationData.SetValue(new UnityApplicationData(s.ApplicationPath,
                                                                                 s.ApplicationContentsPath, s.ApplicationVersion, UnityVersion.RequiresRiderPackage(version)));
                    }));
                    editor.ScriptCompilationDuringPlay.Advise(lifetime,
                                                              s => myHost.PerformModelAction(a => a.ScriptCompilationDuringPlay.Set(ConvertToScriptCompilationEnum(s))));

                    myHost.PerformModelAction(rd =>
                    {
                        rd.GenerateUIElementsSchema.Set((l, u) =>
                                                        editor.GenerateUIElementsSchema.Start(l, u).ToRdTask(l));
                    });

                    TrackActivity(editor, lf);

                    if (!myComponentLifetime.IsTerminated)
                    {
                        myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel",
                                                 () => { UnityModel.SetValue(editor); });
                    }

                    lf.AddAction(() =>
                    {
                        if (!myComponentLifetime.IsTerminated)
                        {
                            myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () =>
                            {
                                myLogger.Info("Wire disconnected.");
                                myHost.PerformModelAction(m => m.SessionInitialized.Value = false);
                                UnityModel.SetValue(null);
                            });
                        }
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }
        private static UnityVersion VersionOfConfiguration(string configuration)
        {
            var match = configurationRegex.Match(configuration);

            return(!match.Success ? null : UnityVersion.Parse(match.Groups["ver"].Value));
        }
Example #12
0
 private static void Parse(UnityVersion obj, string text)
 {
     Assert.AreEqual(obj, UnityVersion.Parse(text));
 }
Example #13
0
 static SemVersion GetPackageUnityVersion(ManifestData manifest)
 {
     return(string.IsNullOrEmpty(manifest.unity) ? new SemVersion(0) : UnityVersion.Parse(manifest.unity));
 }