Exemple #1
0
        public void UpdateOccurrences(
            [NotNull] IList <LocalOccurrence> occurrences,
            [NotNull] IEnumerable <LocalOccurrence> tailOccurrences = null)
        {
            lock (mySyncRoot)
            {
                myOccurrences        = occurrences;
                mySelectedOccurrence = (occurrences.Count == 0) ? null : occurrences[0];

                if (!myShouldDropHighlightings && occurrences.Count == 0)
                {
                    return;
                }

                mySequentialOccurrences.Next(lifetime =>
                {
                    myShellLocks.ExecuteOrQueueReadLock(
                        lifetime, Prefix + "UpdateOccurrence", () =>
                        UpdateOccurrencesHighlighting(lifetime, occurrences));

                    myUpdateSelectedScheduled = true;
                });

                mySequentialFocused.Next(lifetime =>
                {
                    myShellLocks.AssertReadAccessAllowed();

                    myShellLocks.ExecuteOrQueueReadLock(
                        lifetime, Prefix + "UpdateOccurrence", UpdateFocusedOccurrence);
                });
            }
        }
        public ProductSettingsTracker(Lifetime lifetime, ClientFactory clientFactory, IViewable<ISyncSource> syncSources, IFileSystemTracker fileSystemTracker, JetBoxSettingsStorage jetBoxSettings)
        {
            myClientFactory = clientFactory;
              mySettingsStore = jetBoxSettings.SettingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide);
              mySettingsStore.Changed.Advise(lifetime, _ => InitClient());

              myRootFolder = FileSystemPath.Parse("ReSharperPlatform");
              InitClient();

              syncSources.View(lifetime, (lt1, source) =>
            source.FilesToSync.View(lt1, (lt2, fileToSync) =>
            {
              SyncFromCloud(fileToSync.Value);

              var fileTrackingLifetime = new SequentialLifetimes(lt2);
              fileToSync.Change.Advise(lt2,
            args =>
            {
              var path = args.Property.Value;
              if (lifetime.IsTerminated || path.IsNullOrEmpty())
              {
                fileTrackingLifetime.TerminateCurrent();
              }
              else
              {
                fileTrackingLifetime.Next(lt =>
                    fileSystemTracker.AdviseFileChanges(lt, path,
                      delta => delta.Accept(new FileChangesVisitor(myClient, myRootFolder))));
              }
            });
            }));
        }
        private void ShowRefactoringAdvice(IHighlighter highlighter, InplaceRefactoringInfo refactoringInfo)
        {
            sequentialLifetimes.Next(refactoringLifetime =>
            {
                var message = GetMessage();
                var options = GetOptions(refactoringInfo);
                agent.ShowBalloon(refactoringLifetime, string.Empty, message, options, new[] { "Cancel" }, false,
                                  balloonLifetime =>
                {
                    currentHighlighter = highlighter;

                    agent.ButtonClicked.Advise(balloonLifetime, _ => sequentialLifetimes.TerminateCurrent());
                    agent.BalloonOptionClicked.Advise(balloonLifetime, tag =>
                    {
                        // Terminate first. This kills the balloon window before we start
                        // the refactoring UI. If we start the refactoring UI first, I think
                        // it picks up the balloon window as its parent, and it closes when
                        // the balloon closes
                        sequentialLifetimes.TerminateCurrent();

                        var action = tag as Action;
                        if (action != null)
                        {
                            action();
                        }
                    });
                });
            });
        }
Exemple #4
0
        private void CreateProtocols(FileSystemPath portFileFullPath)
        {
            if (!portFileFullPath.ExistsFile)
            {
                return;
            }

            var text = File.ReadAllText(portFileFullPath.FullPath);

            if (!int.TryParse(text, out var port))
            {
                myLogger.Error("Couldn't parse port for from file:{0}, text:{1}", portFileFullPath, text);
                return;
            }

            var modelLifetime = myConnectionLifetimeProducer.Next();

            myLogger.Info("Creating SocketWire with port = {0}", port);
            var wire = new SocketWire.Client(modelLifetime, myDispatcher, port, "UnrealEditorClient");

            wire.Connected.Advise(modelLifetime, isConnected => myUnrealHost.PerformModelAction(riderModel =>
                                                                                                riderModel.IsConnectedToUnrealEditor.SetValue(isConnected)));

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

            wire.Connected.WhenTrue(modelLifetime, lifetime =>
            {
                myLogger.Info("Wire connected");
                ResetModel(lifetime, protocol);
            });
        }
        public void CreateNew(Lifetime clientLifetime, Action <Lifetime> init)
        {
            balloonLifetimes.Next(balloonLifetime =>
            {
                balloonWindow = new BalloonWindow();
                balloonWindow.ButtonClicked += OnButtonClicked;
                balloonWindow.OptionClicked += OnBalloonOptionClicked;

                host = new BalloonWindowHost(balloonWindow);

                // If the client wants to hide the balloon, they can terminate clientLifetime
                // If another client calls CreateNew, balloonLifetimes.Next terminates
                // balloonLifetime. Whichever lifetime terminates first will cause
                // combinedLifetime to terminate, closing the window.
                var combinedLifetime = Lifetimes.CreateIntersection2(clientLifetime, balloonLifetime).Lifetime;
                combinedLifetime.AddAction(() =>
                {
                    if (host != null)
                    {
                        host.Close();
                        host          = null;
                        balloonWindow = null;
                    }
                });

                init(combinedLifetime);
            });
        }
        public ProductSettingsTracker(Lifetime lifetime, IProductNameAndVersion product, ClientFactory clientFactory, GlobalPerProductStorage globalPerProductStorage, IFileSystemTracker fileSystemTracker, JetBoxSettingsStorage jetBoxSettings)
        {
            myClientFactory = clientFactory;
              mySettingsStore = jetBoxSettings.SettingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide);
              mySettingsStore.Changed.Advise(lifetime, _ => InitClient());

              myRootFolder = FileSystemPath.Parse(product.ProductName);
              InitClient();

              var productSettingsPath = globalPerProductStorage.XmlFileStorage.Path;

              SyncFromCloud(productSettingsPath.Value);

              var fileTrackingLifetime = new SequentialLifetimes(lifetime);
              productSettingsPath.Change.Advise(lifetime,
            args =>
            {
              var path = args.Property.Value;
              if (lifetime.IsTerminated || path.IsNullOrEmpty())
              {
            fileTrackingLifetime.TerminateCurrent();
              }
              else
              {
            fileTrackingLifetime.Next(lt => fileSystemTracker.AdviseFileChanges(lt, path, delta => delta.Accept(new FileChangesVisitor(myClient, myRootFolder))));
              }
            });
        }
Exemple #7
0
        public void TestFailedInNext()
        {
            var sequence = new SequentialLifetimes(TestLifetime);
            var sb       = new StringBuilder();

            try
            {
                sequence.Next(lifetime =>
                {
                    lifetime.Bracket(
                        () => sb.AppendLine($"start"),
                        () => sb.AppendLine($"end"));

                    sb.AppendLine("Before exception");
                    throw new Exception("Expected");
                });
            }
            catch (Exception e) when(e.Message == "Expected")
            {
                sb.AppendLine("Expected exception");
            }

            Assert.IsTrue(sequence.IsCurrentTerminated);
            Assert.AreEqual("start\nBefore exception\nend\nExpected exception\n", sb.ToString().Replace("\r\n", "\n"));
        }
        public ProductSettingsTracker(Lifetime lifetime, ClientFactory clientFactory, IViewable <ISyncSource> syncSources, IFileSystemTracker fileSystemTracker, JetBoxSettingsStorage jetBoxSettings)
        {
            myClientFactory = clientFactory;
            mySettingsStore = jetBoxSettings.SettingsStore.BindToContextLive(lifetime, ContextRange.ApplicationWide);
            mySettingsStore.Changed.Advise(lifetime, _ => InitClient());

            myRootFolder = FileSystemPath.Parse("ReSharperPlatform");
            InitClient();

            syncSources.View(lifetime, (lt1, source) =>
                             source.FilesToSync.View(lt1, (lt2, fileToSync) =>
            {
                SyncFromCloud(fileToSync.Value);

                var fileTrackingLifetime = new SequentialLifetimes(lt2);
                fileToSync.Change.Advise(lt2,
                                         args =>
                {
                    var path = args.Property.Value;
                    if (lifetime.IsTerminated || path.IsNullOrEmpty())
                    {
                        fileTrackingLifetime.TerminateCurrent();
                    }
                    else
                    {
                        fileTrackingLifetime.Next(lt =>
                                                  fileSystemTracker.AdviseFileChanges(lt, path,
                                                                                      delta => delta.Accept(new FileChangesVisitor(myClient, myRootFolder))));
                    }
                });
            }));
        }
Exemple #9
0
        public void ReentrancyPriorityAdviceTest()
        {
            using var lifetimeDefinition = new LifetimeDefinition();
            var lifetime = lifetimeDefinition.Lifetime;

            var priorityAdvice = 0;
            var advice1        = 0;
            var advice2        = 0;

            var signal    = new Signal <Unit>();
            var lifetimes = new SequentialLifetimes(TestLifetime);

            signal.Advise(lifetime, _ =>
            {
                advice1++;
                using (Signal.PriorityAdviseCookie.Create())
                {
                    signal.Advise(lifetimes.Next(), _ => priorityAdvice++);
                }
            });

            signal.Advise(lifetime, _ => advice2++);

            for (int i = 0; i < 1000; i++)
            {
                signal.Fire();

                Assert.AreEqual(i + 1, advice1);
                Assert.AreEqual(i + 1, advice2);
                Assert.AreEqual(i, priorityAdvice);
            }
        }
Exemple #10
0
 private void ShowBalloon(string header, string message, IList <BalloonOption> options, params string[] buttons)
 {
     lifetimes.Next(balloonLifetime =>
     {
         var activate = ShowActivated.IsChecked.HasValue && ShowActivated.IsChecked.Value;
         agent.ShowBalloon(balloonLifetime, header, message, options, buttons, activate, _ => { });
     });
 }
        private void CreateProtocol(FileSystemPath protocolInstancePath, Solution solution)
        {
            int port;

            try
            {
                var protocolInstance =
                    JsonConvert.DeserializeObject <ProtocolInstance>(protocolInstancePath.ReadAllText2().Text);
                port = protocolInstance.port_id;
            }
            catch (Exception e)
            {
                myLogger.Warn($"Unable to parse {protocolInstancePath}" + Environment.NewLine + e);
                return;
            }

            myLogger.Info($"UNITY_Port {port}.");

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

                myLogger.Info("Creating SocketWire with port = {0}", port);
                var wire = new SocketWire.Client(lifetime, myDispatcher, port, "UnityClient");
                wire.Connected.WhenTrue(lifetime, lf =>
                {
                    myLogger.Info("WireConnected.");

                    var protocol = new Protocol("UnityEditorPlugin", new Serializers(), new Identities(IdKind.Client), myDispatcher, wire);
                    var model    = new UnityModel(lf, protocol);
                    model.IsBackendConnected.Set(rdVoid => true);
                    model.RiderProcessId.SetValue(Process.GetCurrentProcess().Id);
                    solution.SetCustomData("UNITY_SessionInitialized", "true");

                    SubscribeToLogs(lf, model, solution);
                    SubscribeToOpenFile(model, solution);
                    model.Play.AdviseNotNull(lf, b => solution.SetCustomData("UNITY_Play", b.ToString().ToLower()));
                    model.Pause.AdviseNotNull(lf, b => solution.SetCustomData("UNITY_Pause", b.ToString().ToLower()));

                    myLocks.ExecuteOrQueueEx(myLifetime, "setModel",
                                             () => { myUnityModel.SetValue(model, myReadonlyToken); });
                    lf.AddAction(() =>
                    {
                        myLocks.ExecuteOrQueueEx(myLifetime, "clearModel", () =>
                        {
                            myLogger.Info("Wire disconnected.");
                            solution.SetCustomData("UNITY_SessionInitialized", "false");
                            myUnityModel.SetValue(null, myReadonlyToken);
                        });
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }
        public void TestTerminateCurrent02()
        {
            var sb = new StringBuilder();
            var sequentialLifetimes = new SequentialLifetimes(TestLifetime);

            sequentialLifetimes.Next(lifetime => lifetime.OnTermination(() =>
            {
                sb.Append("T1");
                Assert.IsTrue(lifetime.IsNotAlive, "lifetime.IsNotAlive");
                Assert.IsTrue(sequentialLifetimes.IsCurrentTerminated, "sequentialLifetimes.IsCurrentTerminated");
            }));
            sequentialLifetimes.Next(lifetime =>
            {
                sb.Append("N2");
            });

            Assert.AreEqual("T1N2", sb.ToString());
        }
        public TodoItemsCountProvider(
            Lifetime lifetime,
            IPrimaryTodoManager primaryTodoManager,
            SolutionSettingsCache solutionSettingsCache,
            TodoItemsCountDefinitionsCachedSettingsReader todoItemsCountDefinitionsCachedSettingsReader,
            IEnumerable <ITodoItemsCountConsumer> todoItemsCountConsumers,
            ISettingsStore settingsStore)
        {
            _primaryTodoManager = primaryTodoManager;
            _settingsCache      = solutionSettingsCache;
            _todoItemsCountDefinitionsCachedSettingsReader = todoItemsCountDefinitionsCachedSettingsReader;
            _todoItemsCountConsumers = todoItemsCountConsumers.ToIReadOnlyList();

            _primaryTodoManager.FilesWereUpdated.Advise(lifetime, files =>
            {
                // Check for invalid changed files, else we'll get "not valid" exceptions in the 'AllItems' access
                // later (at least as observed during unit test shut down):
                if (files.WhereNotNull().All(x => x.IsValid()))
                {
                    UpdateTodoItemsCounts();
                }
            });

            var settingsCacheGetDataSequentialLifeTime = new SequentialLifetimes(lifetime);

            _currentSettingsCacheLifeTime = settingsCacheGetDataSequentialLifeTime.Next();

            settingsStore.AdviseChange(lifetime, _todoItemsCountDefinitionsCachedSettingsReader.KeyExposed, () =>
            {
                // We use the following lifetime to solve the issue that this 'ISettingsStore.AdviseChange()' callback
                // arrives earlier than the one used in the cache. => The cache has still the old value when accessed
                // in 'UpdateTodoItemsCounts()'. => Terminate the cache lifetime explicitly.
                _currentSettingsCacheLifeTime = settingsCacheGetDataSequentialLifeTime.Next();

                UpdateTodoItemsCounts();
            });

            foreach (var consumer in _todoItemsCountConsumers)
            {
                consumer.UpdateRequestSignal.Advise(lifetime, () => { UpdateTodoItemsCounts(); });
            }

            // IDEA: Combine the three event sources and execute update in background thread?
        }
        public void TestTerminateCurrent01()
        {
            var sequentialLifetimes = new SequentialLifetimes(TestLifetime);

            sequentialLifetimes.Next(lifetime => lifetime.OnTermination(() =>
            {
                Assert.IsTrue(lifetime.IsNotAlive, "lifetime.IsNotAlive");
                Assert.IsTrue(sequentialLifetimes.IsCurrentTerminated, "sequentialLifetimes.IsCurrentTerminated");
            }));
            sequentialLifetimes.TerminateCurrent();
        }
Exemple #15
0
        public static void View <T>(this IReadonlyProperty <T> me, Lifetime lifetime, Action <Lifetime, T> handler)
        {
            if (!lifetime.IsAlive)
            {
                return;
            }

            // nested lifetime is needed due to exception that could be thrown
            // while viewing a property change right at the moment of <param>lifetime</param>'s termination
            // but before <param>handler</param> gets removed
            var lf  = lifetime == Lifetime.Eternal ? lifetime : Lifetime.Define(lifetime).Lifetime;
            var seq = new SequentialLifetimes(lf);

            me.Advise(lf, v => handler(seq.Next(), v));
        }
        private void SubscribeToSessionLaunch(Lifetime sessionLifetime, IUnitTestSession session)
        {
            var sequentialLifetimes = new SequentialLifetimes(sessionLifetime);

            session.Launch.Change.Advise(sessionLifetime, args =>
            {
                if (args.HasNew && args.New != null)
                {
                    sequentialLifetimes.Next(launchLifetime =>
                    {
                        SubscribeToLaunchState(launchLifetime, session, args.New.State);
                    });
                }
            });
        }
Exemple #17
0
        public void TestTerminateInNext()
        {
            var sequence = new SequentialLifetimes(TestLifetime);
            var sb       = new StringBuilder();

            sequence.Next(lifetime =>
            {
                lifetime.Bracket(
                    () => sb.AppendLine($"start"),
                    () => sb.AppendLine($"end"));
                sb.AppendLine("Before terminate");
                sequence.TerminateCurrent();
                sb.AppendLine("After terminate");
            });

            Assert.IsTrue(sequence.IsCurrentTerminated);
            Assert.AreEqual("start\nBefore terminate\nAfter terminate\nend\n", sb.ToString().Replace("\r\n", "\n"));
        }
Exemple #18
0
        public void TestSimple()
        {
            var sequence = new SequentialLifetimes(TestLifetime);
            var sb       = new StringBuilder();
            var expected = new StringBuilder();

            const int max = 3;

            for (int i = 0; i < max; i++)
            {
                sb.AppendLine($"before {i}");
                sequence.Next(lifetime =>
                {
                    var c = i;
                    lifetime.Bracket(
                        () => sb.AppendLine($"start {c}"),
                        () => sb.AppendLine($"end {c}"));
                    sb.AppendLine($"in {c}");
                });


                if (i == 0)
                {
                    expected.AppendLine($"before {i}");
                }

                expected.AppendLine($"start {i}");
                expected.AppendLine($"in {i}");

                if (i != max - 1)
                {
                    expected.AppendLine($"before {i+1}");
                    expected.AppendLine($"end {i}");
                }
            }

            Assert.IsFalse(sequence.IsCurrentTerminated);
            Assert.AreEqual(expected.ToString(), sb.ToString());

            sequence.TerminateCurrent();
            Assert.IsTrue(sequence.IsCurrentTerminated);
            expected.AppendLine($"end {max - 1}");
            Assert.AreEqual(expected.ToString(), sb.ToString());
        }
Exemple #19
0
 public void StartServerToClientMessaging()
 {
     myServerToClientLifetime.Next();
 }
Exemple #20
0
        private void Login()
        {
            myLifetimes.Next(lifetime =>
            {
                myClient.UserLogin = null;
                myClient.GetTokenAsync(
                    login =>
                {
                    var tcpListener = new TcpListener(IPAddress.Loopback, 0);
                    int port;
                    try
                    {
                        tcpListener.Start();
                        port = ((IPEndPoint)tcpListener.LocalEndpoint).Port;
                    }
                    finally
                    {
                        tcpListener.Stop();
                    }
                    var callbackUri = string.Format("http://{0}:{1}/", "localhost", port);
                    var server      = new HttpListener();
                    server.Prefixes.Add(callbackUri);
                    server.Start();

                    lifetime.AddDispose(server);
                    server.BeginGetContext(ar =>
                    {
                        myClient.Logger.CatchAsOuterDataError(() =>
                        {
                            if (lifetime.IsTerminated)
                            {
                                return;
                            }
                            var context = server.EndGetContext(ar);
                            // Write a response.
                            using (var writer = new StreamWriter(context.Response.OutputStream))
                            {
                                string response = @"<html>
    <head>
      <title>JetBox - OAuth Authentication</title>
    </head>
    <body>
      <h1>Authorization for JetBox</h1>
      <p>The application has received your response. You can close this window now.</p>
      <script type='text/javascript'>
        window.setTimeout(function() { window.open('', '_self', ''); window.close(); }, 100);
        if (window.opener) { window.opener.checkToken(); }
       </script>
    </body>
  </html>";
                                writer.WriteLine(response);
                                writer.Flush();
                            }
                            context.Response.OutputStream.Flush();
                            context.Response.OutputStream.Close();
                            context.Response.Close();
                            GetInfo();
                        });
                    }, null);
                    Environment.OpensUri.OpenUri(new Uri(myClient.BuildAuthorizeUrl(callbackUri)));
                },
                    myClient.LogException);
            });
        }
Exemple #21
0
 public void StartClientToServerMessaging()
 {
     myClientToServerLifetime.Next();
 }
        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);
            }
        }
Exemple #23
0
        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");
                wire.Connected.WhenTrue(lifetime, lf =>
                {
                    myLogger.Info("WireConnected.");

                    var protocol = new Protocol("UnityEditorPlugin", new Serializers(),
                                                new Identities(IdKind.Client), myDispatcher, wire);
                    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.AdviseNotNull(lf, b => myHost.PerformModelAction(rd => rd.Play.SetValue(b)));
                    editor.Pause.AdviseNotNull(lf, b => myHost.PerformModelAction(rd => rd.Pause.SetValue(b)));


                    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.ShowGameObjectOnScene.Advise(lf, v => editor.ShowGameObjectOnScene.Fire(v.ConvertToUnityModel())));

                    // pass all references to Unity TODO temp workaround, replace with async api
                    myHost.PerformModelAction(t => t.FindUsageResults.Advise(lf, v => editor.FindUsageResults.Fire(v.ConvertToUnityModel())));

                    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.ApplicationPath.Advise(lifetime,
                                                  s => myHost.PerformModelAction(a => a.ApplicationPath.SetValue(s)));
                    editor.ApplicationContentsPath.Advise(lifetime,
                                                          s => myHost.PerformModelAction(a => a.ApplicationContentsPath.SetValue(s)));
                    editor.NotifyIsRecompileAndContinuePlaying.AdviseOnce(lifetime,
                                                                          s => myHost.PerformModelAction(a => a.NotifyIsRecompileAndContinuePlaying.Fire(s)));

                    BindPluginPathToSettings(lf, editor);

                    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);
            }
        }
Exemple #24
0
 private void OnBuildBegin(vsBuildScope scope, vsBuildAction action)
 {
     sequentialLifetimes.Next(buildLifetime => agent.Play(buildLifetime, "Processing"));
 }
Exemple #25
0
        private void CreateProtocol(FileSystemPath protocolInstancePath)
        {
            var protocolInstance = GetProtocolInstanceData(protocolInstancePath);

            if (protocolInstance == null)
            {
                return;
            }

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

            if (protocolInstance.ProtocolGuid != ProtocolCompatibility.ProtocolGuid)
            {
                OnOutOfSync(myLifetime);
                myLogger.Info("Avoid attempt to create protocol, incompatible.");
                return;
            }

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

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

                var protocol = new Rd.Impl.Protocol("UnityEditorPlugin", new Serializers(thisSessionLifetime, null, null),
                                                    new Identities(IdKind.Client), myDispatcher, wire, thisSessionLifetime)
                {
                    ThrowErrorOnOutOfSyncModels = false
                };

                protocol.OutOfSyncModels.AdviseOnce(thisSessionLifetime, _ => OnOutOfSync(thisSessionLifetime));

                wire.Connected.WhenTrue(thisSessionLifetime, connectionLifetime =>
                {
                    myLogger.Info("WireConnected.");

                    var backendUnityModel = new BackendUnityModel(connectionLifetime, protocol);

                    SafeExecuteOrQueueEx("setModel",
                                         () => myBackendUnityHost.BackendUnityModel.SetValue(backendUnityModel));

                    connectionLifetime.OnTermination(() =>
                    {
                        SafeExecuteOrQueueEx("clearModel", () =>
                        {
                            myLogger.Info("Wire disconnected.");

                            // Clear model
                            myBackendUnityHost.BackendUnityModel.SetValue(null);
                        });
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }
        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($"UNITY_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");
                wire.Connected.WhenTrue(lifetime, lf =>
                {
                    myLogger.Info("WireConnected.");

                    var protocol = new Protocol("UnityEditorPlugin", new Serializers(),
                                                new Identities(IdKind.Client), myDispatcher, wire);
                    var model = new EditorPluginModel(lf, protocol);
                    model.IsBackendConnected.Set(rdVoid => true);
                    var frontendProcess = Process.GetCurrentProcess().GetParent();
                    if (frontendProcess != null)
                    {
                        model.RiderProcessId.SetValue(frontendProcess.Id);
                    }

                    myHost.SetModelData("UNITY_SessionInitialized", "true");

                    SubscribeToLogs(lf, model);
                    SubscribeToOpenFile(model);
                    model.Play.AdviseNotNull(lf, b => myHost.PerformModelAction(a => a.Play.SetValue(b)));
                    model.Pause.AdviseNotNull(lf, b => myHost.SetModelData("UNITY_Pause", b.ToString().ToLower()));

                    // 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
                    model.EditorLogPath.Advise(lifetime,
                                               s => myHost.PerformModelAction(a => a.EditorLogPath.SetValue(s)));
                    model.PlayerLogPath.Advise(lifetime,
                                               s => myHost.PerformModelAction(a => a.PlayerLogPath.SetValue(s)));

                    model.ApplicationPath.Advise(lifetime,
                                                 s => myHost.PerformModelAction(a => a.ApplicationPath.SetValue(s)));
                    model.ApplicationContentsPath.Advise(lifetime,
                                                         s => myHost.PerformModelAction(a => a.ApplicationContentsPath.SetValue(s)));

                    BindPluginPathToSettings(lf, model);

                    TrackActivity(model, lf);

                    if (!myComponentLifetime.IsTerminated)
                    {
                        myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel",
                                                 () => { myUnityModel.SetValue(model, myReadonlyToken); });
                    }

                    lf.AddAction(() =>
                    {
                        if (!myComponentLifetime.IsTerminated)
                        {
                            myLocks.ExecuteOrQueueEx(myComponentLifetime, "clearModel", () =>
                            {
                                myLogger.Info("Wire disconnected.");
                                myHost.SetModelData("UNITY_SessionInitialized", "false");
                                myUnityModel.SetValue(null, myReadonlyToken);
                            });
                        }
                    });
                });
            }
            catch (Exception ex)
            {
                myLogger.Error(ex);
            }
        }