public bool HasNonCompatiblePackagesCombination(bool isCoverage, out string message)
        {
            message = string.Empty;

            if (myUnityVersion.GetActualVersionForSolution() < new Version("2019.2"))
            {
                return(false);
            }

            var manifestJsonFile = mySolution.SolutionDirectory.Combine("Packages/manifest.json");

            if (manifestJsonFile.ExistsFile)
            {
                var text     = manifestJsonFile.ReadAllText2().Text;
                var packages = ManifestJson.FromJson(text);

                var testFrameworkPackageId     = "com.unity.test-framework";
                var riderPackageId             = "com.unity.ide.rider";
                var testFrameworkMarketingName = "Test Framework";
                var riderMarketingName         = "Rider Editor";

                if (PackageIsMissing(ref message, packages, testFrameworkPackageId, testFrameworkMarketingName))
                {
                    return(true);
                }
                if (PackageIsMissing(ref message, packages, riderPackageId, riderMarketingName))
                {
                    return(true);
                }

                var riderPackageVersion  = packages[riderPackageId];
                var testFrameworkVersion = packages[testFrameworkPackageId];
                if (IsOldPackage(ref message, riderPackageVersion, riderMarketingName, "1.1.1"))
                {
                    return(true);
                }
                if (IsOldPackage(ref message, testFrameworkVersion, testFrameworkMarketingName, "1.1.1"))
                {
                    return(true);
                }

                if (isCoverage && packages.ContainsKey(riderPackageId) && packages.ContainsKey(testFrameworkPackageId))
                {
                    // https://youtrack.jetbrains.com/issue/RIDER-35880
                    if (riderPackageVersion != null && riderPackageVersion < new Version("1.2.0") &&
                        testFrameworkVersion != null &&
                        testFrameworkVersion >= new Version("1.1.5"))
                    {
                        message = $"Update {riderMarketingName} package to v.1.2.0 or later in Unity Package Manager. {HelpLink}";
                        return(true);
                    }
                }
            }

            // todo: package may be installed locally, ignore this possibility for now
            // var localPackage = mySolution.SolutionDirectory.Combine("Packages/com.unity.ide.rider/package.json");

            return(false);
        }
Example #2
0
        private FileID GetCorrespondingSourceObjectFileId(IYamlDocument document)
        {
            if (myVersion.GetActualVersionForSolution().Major == 2017)
            {
                return(document.GetUnityObjectPropertyValue(UnityYamlConstants.CorrespondingSourceObjectProperty2017)?.AsFileID());
            }

            return(document.GetUnityObjectPropertyValue(UnityYamlConstants.CorrespondingSourceObjectProperty)?.AsFileID() ??
                   document.GetUnityObjectPropertyValue(UnityYamlConstants.CorrespondingSourceObjectProperty2017)?.AsFileID());
        }
        private void NotifyFrontend(UnityHost host, UnityVersion unityVersion)
        {
            host.PerformModelAction(rd =>
            {
                // if model is there, then ApplicationPath was already set via UnityEditorProtocol, it would be more correct than any counted value
                if (myUnityEditorProtocol.UnityModel.Value != null)
                {
                    return;
                }

                var version = unityVersion.GetActualVersionForSolution();
                var info    = UnityInstallationFinder.GetApplicationInfo(version, unityVersion);
                if (info == null)
                {
                    return;
                }

                var contentsPath = UnityInstallationFinder.GetApplicationContentsPath(info.Path);
                rd.UnityApplicationData.SetValue(new UnityApplicationData(info.Path.FullPath,
                                                                          contentsPath.FullPath,
                                                                          UnityVersion.VersionToString(info.Version),
                                                                          UnityVersion.RequiresRiderPackage(info.Version)
                                                                          ));
            });
        }
Example #4
0
        private static void NotifyFrontend(UnityHost host, UnityVersion unityVersion)
        {
            var version = unityVersion.GetActualVersionForSolution();
            var info    = UnityInstallationFinder.GetApplicationInfo(version);

            if (info == null)
            {
                return;
            }

            host.PerformModelAction(rd =>
            {
                // ApplicationPath may be already set via UnityEditorProtocol, which is more accurate
                if (!rd.ApplicationPath.HasValue())
                {
                    rd.ApplicationPath.SetValue(info.Path.FullPath);
                }
                if (!rd.ApplicationContentsPath.HasValue())
                {
                    var contentsPath = UnityInstallationFinder.GetApplicationContentsPath(version);
                    if (contentsPath != null)
                    {
                        rd.ApplicationContentsPath.SetValue(contentsPath.FullPath);
                    }
                }
                if (!rd.ApplicationVersion.HasValue() && info.Version != null)
                {
                    rd.ApplicationVersion.SetValue(UnityVersion.VersionToString(info.Version));
                }
            });
        }
        public UnityInstallationSynchronizer(Lifetime lifetime, UnityReferencesTracker referencesTracker,
                                             UnityHost host, UnityInstallationFinder finder, UnityVersion unityVersion)
        {
            referencesTracker.HasUnityReference.Advise(lifetime, hasReference =>
            {
                if (!hasReference)
                {
                    return;
                }
                var version = unityVersion.GetActualVersionForSolution();
                var path    = finder.GetApplicationPath(version);
                if (path == null)
                {
                    return;
                }

                var contentPath = finder.GetApplicationContentsPath(version);

                host.PerformModelAction(rd =>
                {
                    // ApplicationPath may be already set via UnityEditorProtocol, which is more accurate
                    if (!rd.ApplicationPath.HasValue())
                    {
                        rd.ApplicationPath.SetValue(path.FullPath);
                    }
                    if (!rd.ApplicationContentsPath.HasValue())
                    {
                        rd.ApplicationContentsPath.SetValue(contentPath.FullPath);
                    }
                });
            });
        }
        private static void NotifyFrontend(UnityHost host, UnityVersion unityVersion)
        {
            var version         = unityVersion.GetActualVersionForSolution();
            var applicationPath = unityVersion.GetActualAppPathForSolution();

            if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.MacOsX && !applicationPath.ExistsDirectory ||
                PlatformUtil.RuntimePlatform != PlatformUtil.Platform.MacOsX && !applicationPath.ExistsFile)
            {
                var info = UnityInstallationFinder.GetApplicationInfo(version);
                if (info == null)
                {
                    return;
                }
                applicationPath = info.Path;
                version         = info.Version;
            }

            host.PerformModelAction(rd =>
            {
                // ApplicationPath may be already set via UnityEditorProtocol, which will obviously be correct
                if (!rd.ApplicationPath.HasValue())
                {
                    rd.ApplicationPath.SetValue(applicationPath.FullPath);
                }

                if (!rd.ApplicationContentsPath.HasValue())
                {
                    var contentsPath = UnityInstallationFinder.GetApplicationContentsPath(applicationPath);
                    if (!contentsPath.IsEmpty)
                    {
                        rd.ApplicationContentsPath.SetValue(contentsPath.FullPath);
                    }
                }
                if (!rd.ApplicationVersion.HasValue() && version != null)
                {
                    rd.ApplicationVersion.SetValue(UnityVersion.VersionToString(version));
                }
            });
        }
Example #7
0
        private void NotifyFrontend(UnityHost host, UnityVersion unityVersion)
        {
            var version         = unityVersion.GetActualVersionForSolution();
            var applicationPath = unityVersion.GetActualAppPathForSolution();

            if (PlatformUtil.RuntimePlatform == PlatformUtil.Platform.MacOsX && !applicationPath.ExistsDirectory ||
                PlatformUtil.RuntimePlatform != PlatformUtil.Platform.MacOsX && !applicationPath.ExistsFile)
            {
                var info = UnityInstallationFinder.GetApplicationInfo(version);
                if (info == null)
                {
                    return;
                }
                applicationPath = info.Path;
                version         = info.Version;
            }

            host.PerformModelAction(rd =>
            {
                // if model is there, then ApplicationPath was already set via UnityEditorProtocol, it would be more correct than any counted value
                if (myUnityEditorProtocol.UnityModel.Value != null)
                {
                    return;
                }

                rd.ApplicationPath.SetValue(applicationPath.FullPath);
                var contentsPath = UnityInstallationFinder.GetApplicationContentsPath(applicationPath);
                if (!contentsPath.IsEmpty)
                {
                    rd.ApplicationContentsPath.SetValue(contentsPath.FullPath);
                }
                if (version != null)
                {
                    rd.ApplicationVersion.SetValue(UnityVersion.VersionToString(version));
                }
            });
        }
Example #8
0
        public UnityInstallationSynchronizer(Lifetime lifetime, UnitySolutionTracker solutionTracker,
                                             UnityHost host, UnityInstallationFinder finder, UnityVersion unityVersion)
        {
            solutionTracker.IsUnityProjectFolder.AdviseNotNull(lifetime, isUnityProjectFolder =>
            {
                if (!isUnityProjectFolder)
                {
                    return;
                }
                var version = unityVersion.GetActualVersionForSolution();
                var info    = finder.GetApplicationInfo(version);
                if (info == null)
                {
                    return;
                }

                var contentPath = finder.GetApplicationContentsPath(version);

                host.PerformModelAction(rd =>
                {
                    // ApplicationPath may be already set via UnityEditorProtocol, which is more accurate
                    if (!rd.ApplicationPath.HasValue())
                    {
                        rd.ApplicationPath.SetValue(info.Path.FullPath);
                    }
                    if (!rd.ApplicationContentsPath.HasValue())
                    {
                        rd.ApplicationContentsPath.SetValue(contentPath.FullPath);
                    }
                    if (!rd.ApplicationVersion.HasValue())
                    {
                        rd.ApplicationVersion.SetValue(UnityVersion.VersionToString(info.Version));
                    }
                });
            });
        }
Example #9
0
 private string GetCorrespondingSourceObjectProperty()
 {
     return(myVersion.GetActualVersionForSolution().Major == 2017
         ? UnityYamlConstants.CorrespondingSourceObjectProperty2017
         : UnityYamlConstants.CorrespondingSourceObjectProperty);
 }
        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 bool DoCopyFiles([NotNull] UnityPluginDetector.InstallationInfo installation, out FileSystemPath installedPath)
        {
            installedPath = null;

            var originPaths = new List <FileSystemPath>();

            originPaths.AddRange(installation.ExistingFiles);

            var backups = originPaths.ToDictionary(f => f, f => f.AddSuffix(".backup"));

            foreach (var originPath in originPaths)
            {
                var backupPath = backups[originPath];
                if (originPath.ExistsFile)
                {
                    originPath.MoveFile(backupPath, true);
                    myLogger.Info($"backing up: {originPath.Name} -> {backupPath.Name}");
                }
                else
                {
                    myLogger.Info($"backing up failed: {originPath.Name} doesn't exist.");
                }
            }

            try
            {
                var editorPluginPathDir  = myPluginPathsProvider.GetEditorPluginPathDir();
                var editorPluginPath     = editorPluginPathDir.Combine(PluginPathsProvider.BasicPluginDllFile);
                var editorFullPluginPath = editorPluginPathDir.Combine(PluginPathsProvider.FullPluginDllFile);

                var targetPath = installation.PluginDirectory.Combine(editorPluginPath.Name);
                try
                {
                    if (myUnityVersion.GetActualVersionForSolution() < new Version("5.6"))
                    {
                        myLogger.Verbose($"Coping {editorPluginPath} -> {targetPath}");
                        editorPluginPath.CopyFile(targetPath, true);
                    }
                    else
                    {
                        myLogger.Verbose($"Coping {editorFullPluginPath} -> {targetPath}");
                        editorFullPluginPath.CopyFile(targetPath, true);
                    }
                }
                catch (Exception e)
                {
                    myLogger.LogException(LoggingLevel.ERROR, e, ExceptionOrigin.Assertion,
                                          $"Failed to copy {editorPluginPath} => {targetPath}");
                    RestoreFromBackup(backups);
                }

                foreach (var backup in backups)
                {
                    backup.Value.DeleteFile();
                }

                installedPath = installation.PluginDirectory.Combine(PluginPathsProvider.BasicPluginDllFile);
                return(true);
            }
            catch (Exception e)
            {
                myLogger.LogExceptionSilently(e);

                RestoreFromBackup(backups);

                return(false);
            }
        }
Example #12
0
        private void InstallPluginIfRequired()
        {
            if (!myUnitySolutionTracker.IsUnityProjectFolder.Value)
            {
                return;
            }

            if (myPluginInstallations.Contains(mySolution.SolutionFilePath))
            {
                return;
            }

            if (!myBoundSettingsStore.GetValue((UnitySettings s) => s.InstallUnity3DRiderPlugin))
            {
                return;
            }

            var versionForSolution = myUnityVersion.GetActualVersionForSolution();

            if (versionForSolution >= new Version("2019.2")) // 2019.2+ would not work fine either without Rider package, and when package is present it loads EditorPlugin directly from Rider installation.
            {
                var installationInfoToRemove = myDetector.GetInstallationInfo(myCurrentVersion, previousInstallationDir: FileSystemPath.Empty);
                var pluginDll =
                    installationInfoToRemove.PluginDirectory.Combine(PluginPathsProvider.BasicPluginDllFile);
                if (pluginDll.ExistsFile)
                {
                    myQueue.Enqueue(() =>
                    {
                        myLogger.Info($"Remove {pluginDll}. Rider package should be used instead.");
                        pluginDll.DeleteFile();
                        FileSystemPath.Parse(pluginDll.FullPath + ".meta").DeleteFile();

                        // jetbrainsDir is usually "Assets\Plugins\Editor\JetBrains", however custom locations were also possible
                        var jetbrainsDir = installationInfoToRemove.PluginDirectory;
                        if (jetbrainsDir.GetChildren().Any() || jetbrainsDir.Name != "JetBrains")
                        {
                            return;
                        }
                        jetbrainsDir.DeleteDirectoryNonRecursive();
                        FileSystemPath.Parse(jetbrainsDir.FullPath + ".meta").DeleteFile();
                        var pluginsEditorDir = jetbrainsDir.Directory;
                        if (pluginsEditorDir.GetChildren().Any() || pluginsEditorDir.Name != "Editor")
                        {
                            return;
                        }
                        pluginsEditorDir.DeleteDirectoryNonRecursive();
                        FileSystemPath.Parse(pluginsEditorDir.FullPath + ".meta").DeleteFile();
                        var pluginsDir = pluginsEditorDir.Directory;
                        if (pluginsDir.GetChildren().Any() || pluginsDir.Name != "Plugins")
                        {
                            return;
                        }
                        pluginsDir.DeleteDirectoryNonRecursive();
                        FileSystemPath.Parse(pluginsDir.FullPath + ".meta").DeleteFile();
                    });
                }
                return;
            }

            // forcing fresh install due to being unable to provide proper setting until InputField is patched in Rider
            // ReSharper disable once ArgumentsStyleNamedExpression
            var installationInfo = myDetector.GetInstallationInfo(myCurrentVersion, previousInstallationDir: FileSystemPath.Empty);

            if (!installationInfo.ShouldInstallPlugin)
            {
                myLogger.Info("Plugin should not be installed.");
                if (installationInfo.ExistingFiles.Count > 0)
                {
                    myLogger.Info("Already existing plugin files:\n{0}",
                                  string.Join("\n", installationInfo.ExistingFiles));
                }

                return;
            }

            QueueInstall(installationInfo);
            myQueue.Enqueue(() =>
            {
                mySolution.Locks.Tasks.StartNew(myLifetime, Scheduling.MainGuard,
                                                () => myRefresher.StartRefresh(RefreshType.Normal));
            });
        }