public static RdTask <T> ToRdTask <T>(this IRdTask <T> task, Lifetime lifetime)
        {
            if (task is RdTask <T> rdTask)
            {
                return(rdTask);
            }

            var newRdTask = new RdTask <T>();

            task.Result.Advise(lifetime, result =>
            {
                switch (result.Status)
                {
                case RdTaskStatus.Success:
                    newRdTask.Set(result.Result);
                    break;

                case RdTaskStatus.Canceled:
                    newRdTask.SetCancelled();
                    break;

                case RdTaskStatus.Faulted:
                    newRdTask.Set(result.Error);
                    break;
                }
            });
            return(newRdTask);
        }
Example #2
0
        private void SupportAbort(object runner)
        {
            var unityTestAssemblyRunnerField =
                runner.GetType().GetField("m_Runner", BindingFlags.Instance | BindingFlags.NonPublic);

            if (unityTestAssemblyRunnerField != null)
            {
                var unityTestAssemblyRunner = unityTestAssemblyRunnerField.GetValue(runner);
                var stopRunMethod           = unityTestAssemblyRunner.GetType()
                                              .GetMethod("StopRun", BindingFlags.Instance | BindingFlags.Public);
                myLaunch.Abort.Set((lifetime, _) =>
                {
                    ourLogger.Verbose("Call StopRun method via reflection.");
                    var task = new RdTask <bool>();
                    try
                    {
                        stopRunMethod.Invoke(unityTestAssemblyRunner, null);
                        task.Set(true);
                    }
                    catch (Exception)
                    {
                        ourLogger.Verbose("Call StopRun method failed.");
                        task.Set(false);
                    }
                    return(task);
                });
            }
        }
Example #3
0
        public LambdaPsiHost(ISolution solution, ISymbolCache symbolCache, PsiIconManager psiIconManager, IconHost iconHost,
                             ProjectModelViewHost projectModelViewHost, IShellLocks locks, ILogger logger)
        {
            _symbolCache          = symbolCache;
            _psiIconManager       = psiIconManager;
            _iconHost             = iconHost;
            _projectModelViewHost = projectModelViewHost;
            _locks  = locks;
            _logger = logger;

            var model = solution.GetProtocolSolution().GetLambdaPsiModel();

            model.DetermineHandlers.Set((lifetime, unit) =>
            {
                var task = new RdTask <List <HandlerCompletionItem> >();
                task.Set(DetermineHandlers(solution));
                return(task);
            });

            model.IsHandlerExists.Set((lifetime, request) =>
            {
                var task       = new RdTask <bool>();
                var className  = request.ClassName;
                var methodName = request.MethodName;
                var projectId  = request.ProjectId;

                var handlerExists = IsHandlerExists(lifetime, projectId, className, methodName);
                task.Set(handlerExists);
                return(task);
            });
        }
Example #4
0
        private static void AdviseRefresh(EditorPluginModel model)
        {
            model.Refresh.Set((l, force) =>
            {
                var task = new RdTask <Unit>();
                ourLogger.Verbose("Refresh: SyncSolution Enqueue");
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force != RefreshType.Normal)
                    {
                        if (force == RefreshType.ForceRequestScriptReload)
                        {
                            ourLogger.Verbose("Refresh: RequestScriptReload");
                            UnityEditorInternal.InternalEditorUtility.RequestScriptReload();
                        }

                        ourLogger.Verbose("Refresh: SyncSolution Started");
                        UnityUtils.SyncSolution();
                        ourLogger.Verbose("Refresh: SyncSolution Completed");
                    }
                    else
                    {
                        ourLogger.Verbose("AutoRefresh is disabled via Unity settings.");
                    }
                    task.Set(Unit.Instance);
                });
                return(task);
            });
        }
Example #5
0
        public override void OnWireReceived(UnsafeReader reader)
        {
            var taskId = RdId.Read(reader);
            var value  = ReadRequestDelegate(SerializationContext, reader);

            if (LogReceived.IsTraceEnabled())
            {
                LogReceived.Trace("endpoint `{0}`::({1}), taskId={2}, request = {3}", Location, RdId, taskId, value.PrintToString());
            }


            RdTask <TRes> rdTask;

            using (UsingDebugInfo()) //now supports only sync handlers
            {
                try
                {
                    rdTask = Handler(myBindLifetime, value);
                }
                catch (OperationCanceledException)
                {
                    rdTask = RdTask <TRes> .Cancelled();
                }
                catch (Exception e)
                {
                    rdTask = RdTask <TRes> .Faulted(e);
                }
            }

            rdTask.Result.Advise(myBindLifetime, result =>
            {
                if (LogSend.IsTraceEnabled())
                {
                    LogSend.Trace("endpoint `{0}`::({1}), taskId={2}, response = {3}", Location, RdId, taskId, result.PrintToString());
                }

                RdTaskResult <TRes> validatedResult;
                try
                {
                    if (result.Status == RdTaskStatus.Success)
                    {
                        AssertNullability(result.Result);
                    }
                    validatedResult = result;
                }
                catch (Exception e)
                {
                    LogSend.Error(e);
                    validatedResult = RdTaskResult <TRes> .Faulted(e);
                }

                Wire.Send(RdId, (writer) =>
                {
                    taskId.Write(writer);
                    RdTaskResult <TRes> .Write(WriteResponseDelegate, SerializationContext, writer, validatedResult);
                });
            });
        }
Example #6
0
        public ProjectProtocolHandler(Lifetime lifetime, IProtocol protocol, ILogger logger)
        {
            logger.Log(LoggingLevel.INFO, $"{protocol.Name} is protocol");
            BsmtRiderModel = new BSMT_RiderModel(lifetime, protocol);
            BSMT_RiderModel.RegisterDeclaredTypesSerializers(protocol.Serializers);

            BsmtRiderModel.FoundBeatSaberLocations
            .Set((t, _) => RdTask <string[]> .Successful(BeatSaberPathUtils.GetInstallDir().ToArray()));
        }
        private static void AdviseRunMethod(EditorPluginModel model)
        {
            model.RunMethodInUnity.Set((lifetime, data) =>
            {
                var task = new RdTask <RunMethodResult>();
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    if (!lifetime.IsAlive)
                    {
                        task.SetCancelled();
                        return;
                    }

                    try
                    {
                        ourLogger.Verbose($"Attempt to execute {data.MethodName}");
                        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
                        var assembly   = assemblies
                                         .FirstOrDefault(a => a.GetName().Name.Equals(data.AssemblyName));
                        if (assembly == null)
                        {
                            throw new Exception($"Could not find {data.AssemblyName} assembly in current AppDomain");
                        }

                        var type = assembly.GetType(data.TypeName);
                        if (type == null)
                        {
                            throw new Exception($"Could not find {data.TypeName} in assembly {data.AssemblyName}.");
                        }

                        var method = type.GetMethod(data.MethodName, BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);

                        if (method == null)
                        {
                            throw new Exception($"Could not find {data.MethodName} in type {data.TypeName}");
                        }

                        try
                        {
                            method.Invoke(null, null);
                        }
                        catch (Exception e)
                        {
                            Debug.LogException(e);
                        }

                        task.Set(new RunMethodResult(true, string.Empty, string.Empty));
                    }
                    catch (Exception e)
                    {
                        ourLogger.Log(LoggingLevel.WARN, $"Execute {data.MethodName} failed.", e);
                        task.Set(new RunMethodResult(false, e.Message, e.StackTrace));
                    }
                });
                return(task);
            });
        }
Example #8
0
        protected override void Start()
        {
            Queue(() =>
            {
                var demoModel = new DemoModel(ModelLifetime, Protocol);

                demoModel.Call.Set((lifetime, c) => RdTask <string> .Successful(c.ToString()));

                demoModel.Callback.Start("Csharp");
            });
        }
        private static void AdviseRefresh(EditorPluginModel model)
        {
            model.Refresh.Set((l, force) =>
            {
                var refreshTask = new RdTask <Unit>();
                void SendResult()
                {
                    if (!EditorApplication.isCompiling)
                    {
                        // ReSharper disable once DelegateSubtraction
                        EditorApplication.update -= SendResult;
                        ourLogger.Verbose("Refresh: SyncSolution Completed");
                        refreshTask.Set(Unit.Instance);
                    }
                }

                ourLogger.Verbose("Refresh: SyncSolution Enqueue");
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force != RefreshType.Normal)
                    {
                        try
                        {
                            if (force == RefreshType.ForceRequestScriptReload)
                            {
                                ourLogger.Verbose("Refresh: RequestScriptReload");
                                UnityEditorInternal.InternalEditorUtility.RequestScriptReload();
                            }

                            ourLogger.Verbose("Refresh: SyncSolution Started");
                            UnityUtils.SyncSolution();
                        }
                        catch (Exception e)
                        {
                            ourLogger.Error("Refresh failed with exception", e);
                        }
                        finally
                        {
                            EditorApplication.update += SendResult;
                        }
                    }
                    else
                    {
                        refreshTask.Set(Unit.Instance);
                        ourLogger.Verbose("AutoRefresh is disabled via Unity settings.");
                    }
                });
                return(refreshTask);
            });
        }
        public LambdaHost(ISolution solution, ISymbolCache symbolCache, PsiIconManager psiIconManager, IconHost iconHost)
        {
            _model          = solution.GetProtocolSolution().GetLambdaModel();
            _symbolCache    = symbolCache;
            _psiIconManager = psiIconManager;
            _iconHost       = iconHost;

            _model.DetermineHandlers.Set((lifetime, unit) =>
            {
                var task = new RdTask <List <HandlerCompletionItem> >();
                task.Set(DetermineHandlers(solution));
                return(task);
            });
        }
Example #11
0
        private void AdviseFrontendToUnityModel(Lifetime lifetime, FrontendBackendModel frontendBackendModel)
        {
            // BackendUnityModel is recreated frequently (e.g. on each AppDomain reload when changing play/edit mode).
            // So subscribe to the frontendBackendModel once and flow in changes only if backendUnityModel is available.
            // Note that we only flow changes, not the current value. Even though these properties are stateful,
            // frontendBackendModel is not the source of truth - values need to flow from backendUnityModel. Also, due
            // to model reload, we go through a few values before we stabilise. E.g.:
            // * User clicks play, fb.Play is true, flows into bu.Play which switches to play mode and causes an
            //   AppDomain reload.
            // * bu.Play becomes false due to AppDomain teardown, flows into fb.Play
            // * BackendUnityModel is torn down and recreated (<- WARNING!)
            // * bu.Play becomes true as Unity enters play mode, flows into fb.Play
            // If we flowed the current value of fb.Play into backendUnityModel when it is recreated, we'd set it to
            // false, triggering play mode to end.
            // Step is simply since it's a non-stateful ISource<T>
            var backendUnityModelProperty = myBackendUnityHost.BackendUnityModel;

            frontendBackendModel.PlayControls.Play.FlowChangesIntoRdDeferred(lifetime,
                                                                             () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Play);
            frontendBackendModel.PlayControls.Pause.FlowChangesIntoRdDeferred(lifetime,
                                                                              () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Pause);
            frontendBackendModel.PlayControls.Step.Advise(lifetime, () => backendUnityModelProperty.Maybe.ValueOrDefault?.PlayControls.Step.Fire());

            // Called from frontend to generate the UIElements schema files
            frontendBackendModel.GenerateUIElementsSchema.Set((l, u) =>
                                                              backendUnityModelProperty.Maybe.ValueOrDefault?.GenerateUIElementsSchema.Start(l, u).ToRdTask(l));

            // Signalled from frontend to select and ping the object in the Project view
            frontendBackendModel.ShowFileInUnity.Advise(lifetime, file =>
                                                        backendUnityModelProperty.Maybe.ValueOrDefault?.ShowFileInUnity.Fire(file));

            // Signalled from fronted to open the preferences window
            frontendBackendModel.ShowPreferences.Advise(lifetime, _ =>
                                                        backendUnityModelProperty.Maybe.ValueOrDefault?.ShowPreferences.Fire());

            // Called from frontend to run a method in unity
            frontendBackendModel.RunMethodInUnity.Set((l, data) =>
            {
                var backendUnityModel = backendUnityModelProperty.Maybe.ValueOrDefault;
                return(backendUnityModel == null
                    ? RdTask <RunMethodResult> .Cancelled()
                    : backendUnityModel.RunMethodInUnity.Start(l, data).ToRdTask(l));
            });

            frontendBackendModel.HasUnsavedScenes.Set((l, u) =>
                                                      backendUnityModelProperty.Maybe.ValueOrDefault?.HasUnsavedScenes.Start(l, u).ToRdTask(l));
        }
        private RdTask <RdProjectOutput> GetProjectOutputModel(Lifetime lifetime, RdGetProjectOutputArgs args)
        {
            var project = GetProject(
                VirtualFileSystemPath.Parse(args.ProjectFilePath, InteractionContext.SolutionContext));
            var targetFramework = project.TargetFrameworkIds
                                  // Take .NET Core first, then .NET Framework, and then .NET Standard. The comparer below will hold this order.
                                  .OrderBy(tfm => (!tfm.IsNetCoreApp, !tfm.IsNetFramework, !tfm.IsNetStandard))
                                  .First();

            _logger.Trace("TFM selected for project {0}: {1}", args, targetFramework);
            var assemblyInfo = project.GetOutputAssemblyInfo(targetFramework).NotNull();

            _logger.Trace("Assembly file path detected for project {0}: {1}", args, assemblyInfo.Location);
            return(RdTask <RdProjectOutput> .Successful(
                       new RdProjectOutput(
                           targetFramework.ToRdTargetFrameworkInfo(),
                           assemblyInfo.Location.ToString())));
        }
Example #13
0
        public void TestBindable()
        {
            ClientWire.AutoTransmitMode = true;
            ServerWire.AutoTransmitMode = true;


            var call1 = new RdCall <Unit, RdSignal <int> >(Serializers.ReadVoid, Serializers.WriteVoid, RdSignal <int> .Read, RdSignal <int> .Write);
            var call2 = new RdCall <Unit, RdSignal <int> >(Serializers.ReadVoid, Serializers.WriteVoid, RdSignal <int> .Read, RdSignal <int> .Write);

            var respSignal           = new RdSignal <int>();
            var endpointLfTerminated = false;

            call2.Set((endpointLf, _) =>
            {
                endpointLf.OnTermination(() => endpointLfTerminated = true);
                return(RdTask <RdSignal <int> > .Successful(respSignal));
            });

            var serverEntity = BindToServer(LifetimeDefinition.Lifetime, call1, ourKey);
            var clientEntity = BindToClient(LifetimeDefinition.Lifetime, call2, ourKey);

            var ld     = new LifetimeDefinition();
            var lf     = ld.Lifetime;
            var signal = call1.Start(lf, Unit.Instance).AsTask().GetOrWait(lf);
            var log    = new List <int>();

            signal.Advise(Lifetime.Eternal, v =>
            {
                log.Add(v);
                Console.WriteLine(v);
            });

            respSignal.Fire(1);
            respSignal.Fire(2);
            respSignal.Fire(3);
            ld.Terminate();
            Assert.False(respSignal.IsBound);

            SpinWaitEx.SpinUntil(() => log.Count >= 3);
            Thread.Sleep(100);
            Assert.AreEqual(new [] { 1, 2, 3 }, log.ToArray());

            Assert.True(endpointLfTerminated);
        }
Example #14
0
 private static void AdviseRefresh(EditorPluginModel model)
 {
     model.Refresh.Set((l, force) =>
     {
         var task = new RdTask <RdVoid>();
         MainThreadDispatcher.Instance.Queue(() =>
         {
             if (!EditorApplication.isPlaying && EditorPrefsWrapper.AutoRefresh || force)
             {
                 UnityUtils.SyncSolution();
             }
             else
             {
                 ourLogger.Verbose("AutoRefresh is disabled via Unity settings.");
             }
             task.Set(RdVoid.Instance);
         });
         return(task);
     });
 }
Example #15
0
        public void TestNullability()
        {
            ClientWire.AutoTransmitMode = true;
            ServerWire.AutoTransmitMode = true;

            var serverEntity = BindToServer(LifetimeDefinition.Lifetime, new RdCall <string, string>(), ourKey);
            var clientEntity = BindToClient(LifetimeDefinition.Lifetime, new RdEndpoint <string, string>(x => x.ToString()), ourKey);

            clientEntity.Reset((lf, req) => RdTask <string> .Successful(req == null ? "NULL" : null));

            Assert.Throws <Assertion.AssertionException>(() => { serverEntity.Sync(null); });

            Assert.Throws <Assertion.AssertionException>(() =>
            {
                using (Log.UsingLogFactory(new TestThrowingLogFactory()))
                {
                    var task = serverEntity.Start("Value");
                    Assert.AreEqual(RdTaskStatus.Faulted, task.Result.Value.Status);
                }
            });
        }
Example #16
0
        private RdTask <RdProjectOutput> GetProjectOutputModel(Lifetime lifetime, RdGetProjectOutputArgs args)
        {
            var projectsHostContainer      = _solution.ProjectsHostContainer();
            var solutionStructureContainer = projectsHostContainer.GetComponent <ISolutionStructureContainer>();
            var projectMark = solutionStructureContainer
                              .GetProjectsByLocation(FileSystemPath.Parse(args.ProjectFilePath))
                              .First();

            var project         = _solution.GetProjectByMark(projectMark).NotNull();
            var targetFramework = project.TargetFrameworkIds
                                  // Take .NET Core first, then .NET Framework, and then .NET Standard. The comparer below will hold this order.
                                  .OrderBy(tfm => (!tfm.IsNetCoreApp, !tfm.IsNetFramework, !tfm.IsNetStandard))
                                  .First();

            _logger.Trace("TFM selected for project {0}: {1}", args, targetFramework);
            var assemblyInfo = project.GetOutputAssemblyInfo(targetFramework).NotNull();

            _logger.Trace("Assembly file path detected for project {0}: {1}", args, assemblyInfo.Location);
            return(RdTask <RdProjectOutput> .Successful(
                       new RdProjectOutput(targetFramework.Name, assemblyInfo.Location.ToString())));
        }
Example #17
0
 private static void AdviseExitUnity(EditorPluginModel model)
 {
     model.ExitUnity.Set((_, rdVoid) =>
     {
         var task = new RdTask <bool>();
         MainThreadDispatcher.Instance.Queue(() =>
         {
             try
             {
                 ourLogger.Verbose("ExitUnity: Started");
                 EditorApplication.Exit(0);
                 ourLogger.Verbose("ExitUnity: Completed");
                 task.Set(true);
             }
             catch (Exception e)
             {
                 ourLogger.Log(LoggingLevel.WARN, "EditorApplication.Exit failed.", e);
                 task.Set(false);
             }
         });
         return(task);
     });
 }
Example #18
0
        public AwsProjectHost(ISolution solution)
        {
            var model = solution.GetProtocolSolution().GetAwsProjectModel();

            model.GetProjectOutput.Set((lifetime, request) =>
            {
                var task = new RdTask <AwsProjectOutput>();
                var assemblyPathPrefix = FileSystemPath.Parse(request.ProjectPath);

                using (ReadLockCookie.Create())
                {
                    var allProjects = solution.GetAllProjects();

                    foreach (var project in allProjects)
                    {
                        var targetFrameworks = project.GetAllTargetFrameworks();
                        foreach (var targetFramework in targetFrameworks)
                        {
                            var assembly = project.GetOutputAssemblyInfo(targetFramework.FrameworkId);
                            if (assembly == null)
                            {
                                continue;
                            }

                            if (assembly.Location.FullPath.StartsWith(assemblyPathPrefix.FullPath))
                            {
                                task.Set(new AwsProjectOutput(assembly.AssemblyNameInfo.Name, assembly.Location.FullPath));
                                return(task);
                            }
                        }
                    }

                    task.SetCancelled();
                    return(task);
                }
            });
        }
        private static UnityModel CreateModel(Protocol protocol, Lifetime lt)
        {
            var isPlayingAction = new Action(() =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    var isPlaying = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying;
                    ourModel?.Maybe.ValueOrDefault?.Play.SetValue(isPlaying);

                    var isPaused = EditorApplication.isPaused;
                    ourModel?.Maybe.ValueOrDefault?.Pause.SetValue(isPaused);
                });
            });
            var model = new UnityModel(lt, protocol);

            isPlayingAction(); // get Unity state
            model.Play.Advise(lt, play =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    var res = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying;
                    if (res != play)
                    {
                        EditorApplication.isPlaying = play;
                    }
                });
            });

            model.Pause.Advise(lt, pause =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    EditorApplication.isPaused = pause;
                });
            });
            model.LogModelInitialized.SetValue(new UnityLogModelInitialized());
            model.Refresh.Set((l, force) =>
            {
                var task = new RdTask <RdVoid>();
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    if (EditorPrefsWrapper.AutoRefresh || force)
                    {
                        UnityUtils.SyncSolution();
                    }
                    else
                    {
                        ourLogger.Verbose("AutoRefresh is disabled via Unity settings.");
                    }
                    task.Set(RdVoid.Instance);
                });
                return(task);
            });
            model.Step.Set((l, x) =>
            {
                var task = new RdTask <RdVoid>();
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    EditorApplication.Step();
                    task.Set(RdVoid.Instance);
                });
                return(task);
            });

            var isPlayingHandler = new EditorApplication.CallbackFunction(() => isPlayingAction());

// left for compatibility with Unity <= 5.5
#pragma warning disable 618
            lt.AddBracket(() => { EditorApplication.playmodeStateChanged += isPlayingHandler; },
                          () => { EditorApplication.playmodeStateChanged -= isPlayingHandler; });
#pragma warning restore 618
            //isPlayingHandler();

            // new api - not present in Unity 5.5
            //lt.AddBracket(() => { EditorApplication.pauseStateChanged+= IsPauseStateChanged(model);},
            //  () => { EditorApplication.pauseStateChanged -= IsPauseStateChanged(model); });

            ourLogger.Verbose("CreateModel finished.");

            return(model);
        }
Example #20
0
 public void Set(Func <TReq, TRes> handler)
 {
     Set((lf, req) => RdTask <TRes> .Successful(handler(req)));
 }
Example #21
0
        internal static void SupportAbortNew(UnitTestLaunch launch)
        {
            try
            {
                const string assemblyName = "UnityEditor.TestRunner";
                const string typeName     = "UnityEditor.TestTools.TestRunner.Api.TestRunnerApi";
                const string methodName   = "CancelAllTestRuns";

                MethodInfo stopRunMethod = null;

                var assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals(assemblyName));
                if (assembly == null)
                {
                    ourLogger.Verbose($"Could not find {assemblyName} in the AppDomain.");
                }
                else
                {
                    var apiType = assembly.GetType(typeName);
                    if (apiType == null)
                    {
                        ourLogger.Verbose($"Could not find {typeName} in the {assemblyName}.");
                    }
                    else
                    {
                        stopRunMethod = apiType.GetMethod(methodName);
                        if (stopRunMethod == null)
                        {
                            ourLogger.Verbose($"Could not find {methodName} in the {typeName}.");
                        }
                    }
                }

                launch.Abort.Set((lifetime, _) =>
                {
                    var task = new RdTask <bool>();

                    if (stopRunMethod != null)
                    {
                        ourLogger.Verbose($"Call {methodName} method via reflection.");
                        try
                        {
                            stopRunMethod.Invoke(null, null);
                            task.Set(true);
                            if (!launch.RunStarted.HasTrueValue()) // if RunStarted never happened
                            {
                                launch.RunResult(new RunResult(false));
                            }
                        }
                        catch (Exception)
                        {
                            ourLogger.Verbose($"Call {methodName} method failed.");
                            task.Set(false);
                        }
                    }
                    else
                    {
                        task.Set(false);
                    }

                    return(task);
                });
            }
            catch (Exception e)
            {
                ourLogger.Error(e, "Unexpected exception in SupportAbortNew");
            }
        }
        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");
                UnityWire.Value = wire;
                wire.BackwardsCompatibleWireFormat = true;

                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.ActualVersionForSolution.Value;
                    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.LastPlayTime.Advise(lf, time => myHost.PerformModelAction(rd => rd.LastPlayTime.SetValue(time)));
                    editor.LastInitTime.Advise(lf, time => myHost.PerformModelAction(rd => rd.LastInitTime.SetValue(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));
                    });

                    editor.BuildLocation.Advise(lf, b => myHost.PerformModelAction(rd => rd.BuildLocation.SetValue(b)));

                    myHost.PerformModelAction(rd =>
                    {
                        rd.RunMethodInUnity.Set((l, data) =>
                        {
                            var editorRdTask = editor.RunMethodInUnity.Start(l, new RunMethodData(data.AssemblyName, data.TypeName, data.MethodName)).ToRdTask(l);
                            var frontendRes  = new RdTask <JetBrains.Rider.Model.RunMethodResult>();

                            editorRdTask.Result.Advise(l, r =>
                            {
                                frontendRes.Set(new JetBrains.Rider.Model.RunMethodResult(r.Result.Success, r.Result.Message, r.Result.StackTrace));
                            });
                            return(frontendRes);
                        });
                    });

                    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);
            }
        }
Example #23
0
 public RdEndpoint(Func <TReq, TRes> handler) : this((lf, req) => RdTask <TRes> .Successful(handler(req)))
 {
 }
Example #24
0
        private static void AdviseUnityActions(EditorPluginModel model, Lifetime connectionLifetime)
        {
            var isPlayingAction = new Action(() =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    var isPlayOrWillChange = EditorApplication.isPlayingOrWillChangePlaymode;
                    var isPlaying          = isPlayOrWillChange && EditorApplication.isPlaying;
                    if (!model.Play.HasValue() || model.Play.HasValue() && model.Play.Value != isPlaying)
                    {
                        model.Play.SetValue(isPlaying);
                    }

                    var isPaused = EditorApplication.isPaused;
                    if (!model.Pause.HasValue() || model.Pause.HasValue() && model.Pause.Value != isPaused)
                    {
                        model.Pause.SetValue(isPaused);
                    }
                });
            });

            isPlayingAction(); // get Unity state
            model.Play.Advise(connectionLifetime, play =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    var res = EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying;
                    if (res != play)
                    {
                        EditorApplication.isPlaying = play;
                    }
                });
            });

            model.Pause.Advise(connectionLifetime, pause =>
            {
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    EditorApplication.isPaused = pause;
                });
            });

            model.Step.Set((l, x) =>
            {
                var task = new RdTask <RdVoid>();
                MainThreadDispatcher.Instance.Queue(() =>
                {
                    EditorApplication.Step();
                    task.Set(RdVoid.Instance);
                });
                return(task);
            });

            var isPlayingHandler = new EditorApplication.CallbackFunction(() => isPlayingAction());

// left for compatibility with Unity <= 5.5
#pragma warning disable 618
            connectionLifetime.AddBracket(() => { EditorApplication.playmodeStateChanged += isPlayingHandler; },
                                          () => { EditorApplication.playmodeStateChanged -= isPlayingHandler; });
#pragma warning restore 618
            // new api - not present in Unity 5.5
            // private static Action<PauseState> IsPauseStateChanged(UnityModel model)
            //    {
            //      return state => model?.Pause.SetValue(state == PauseState.Paused);
            //    }
        }
Example #25
0
        private void ResetModel(Lifetime lf, IProtocol protocol)
        {
            myUnrealHost.PerformModelAction(riderModel =>
            {
                UE4Library.RegisterDeclaredTypesSerializers(riderModel.SerializationContext.Serializers);
                riderModel.EditorId.SetValue(riderModel.EditorId.Value + 1);
            });

            var unrealModel = new RdEditorModel(lf, protocol);

            UE4Library.RegisterDeclaredTypesSerializers(unrealModel.SerializationContext.Serializers);

            unrealModel.AllowSetForegroundWindow.Set((lt, pid) =>
            {
                return(myUnrealHost.PerformModelAction(riderModel =>
                                                       riderModel.AllowSetForegroundWindow.Start(lt, pid)) as RdTask <bool>);
            });

            unrealModel.UnrealLog.Advise(lf,
                                         logEvent =>
            {
                myUnrealHost.PerformModelAction(riderModel => { OnMessageReceived(riderModel, logEvent); });
            });

            unrealModel.OnBlueprintAdded.Advise(lf, blueprintClass =>
            {
                //todo
            });

            unrealModel.Play.Advise(lf, val =>
            {
                myUnrealHost.PerformModelAction(riderModel =>
                {
                    if (PlayedFromRider)
                    {
                        return;
                    }
                    try
                    {
                        PlayedFromUnreal = true;
                        riderModel.Play.Set(val);
                    }
                    finally
                    {
                        PlayedFromUnreal = false;
                    }
                });
            });
            unrealModel.PlayMode.Advise(lf, val =>
            {
                myUnrealHost.PerformModelAction(riderModel =>
                {
                    if (PlayModeFromRider)
                    {
                        return;
                    }
                    try
                    {
                        PlayModeFromUnreal = true;
                        riderModel.PlayMode.Set(val);
                    }
                    finally
                    {
                        PlayModeFromUnreal = false;
                    }
                });
            });

            myUnrealHost.PerformModelAction(riderModel =>
            {
                riderModel.FilterLinkCandidates.Set((lifetime, candidates) =>
                                                    RdTask <ILinkResponse[]> .Successful(candidates
                                                                                         .Select(request => myLinkResolver.ResolveLink(request, unrealModel.IsBlueprintPathName))
                                                                                         .AsArray()));
                riderModel.IsMethodReference.Set((lifetime, methodReference) =>
                {
                    var b = myEditorNavigator.IsMethodReference(methodReference);
                    return(RdTask <bool> .Successful(b));
                });
                riderModel.OpenBlueprint.Advise(lf, blueprintReference =>
                                                OnOpenedBlueprint(unrealModel, blueprintReference));

                riderModel.NavigateToClass.Advise(lf,
                                                  uClass => myEditorNavigator.NavigateToClass(uClass));

                riderModel.NavigateToMethod.Advise(lf,
                                                   methodReference => myEditorNavigator.NavigateToMethod(methodReference));

                riderModel.Play.Advise(lf, val =>
                {
                    if (PlayedFromUnreal)
                    {
                        return;
                    }
                    try
                    {
                        PlayedFromRider = true;
                        unrealModel.Play.Set(val);
                    }
                    finally
                    {
                        PlayedFromRider = false;
                    }
                });

                riderModel.PlayMode.Advise(lf, val =>
                {
                    if (PlayModeFromUnreal)
                    {
                        return;
                    }
                    try
                    {
                        PlayModeFromRider = true;
                        unrealModel.PlayMode.Set(val);
                    }
                    finally
                    {
                        PlayModeFromRider = false;
                    }
                });
                riderModel.FrameSkip.Advise(lf, skip =>
                                            unrealModel.FrameSkip.Fire(skip));
            });

            if (myComponentLifetime.IsAlive)
            {
                myLocks.ExecuteOrQueueEx(myComponentLifetime, "setModel",
                                         () => { myEditorModel.SetValue(unrealModel); });
            }
        }
Example #26
0
        public T4TestHost(
            [NotNull] T4TestModel model,
            [NotNull] SolutionsManager solutionsManager
            )
        {
            model.PreprocessFile.Set(location =>
            {
                using var cookie = ReadLockCookie.Create();
                var solution     = solutionsManager.Solution;
                if (solution == null)
                {
                    return(Unit.Instance);
                }

                var host        = solution.GetComponent <ProjectModelViewHost>();
                var projectFile = host.GetItemById <IProjectFile>(location.Id).NotNull();
                var sourceFile  = projectFile.ToSourceFile().NotNull();
                sourceFile.GetPsiServices().Files.CommitAllDocuments();
                var file = sourceFile.GetPsiFiles(T4Language.Instance).OfType <IT4File>().SingleItem().NotNull();

                var templatePreprocessingManager = solution.GetComponent <IT4TemplatePreprocessingManager>();
                templatePreprocessingManager.Preprocess(file);
                return(Unit.Instance);
            });
            model.WaitForIndirectInvalidation.Set((lifetime, unit) =>
            {
                using var cookie = ReadLockCookie.Create();
                var solution     = solutionsManager.Solution;
                if (solution == null)
                {
                    return(RdTask <Unit> .Successful(Unit.Instance));
                }
                var cache = solution.GetComponent <T4FileDependencyCache>();

                var result = new RdTask <Unit>();

                void Requeue(int n)
                {
                    if (n == 1)
                    {
                        result.Set(Unit.Instance);
                        return;
                    }
                    solution.Locks.Queue(lifetime, "T4TestHost::.ctor::lambda::Requeue", () =>
                    {
                        if (cache.HasDirtyFiles)
                        {
                            Commit(n - 1);
                        }
                        else
                        {
                            Requeue(n - 1);
                        }
                    });
                }

                void Commit(int n) => solution.GetPsiServices().Files.ExecuteAfterCommitAllDocuments(() => Requeue(n));
                // First commit applies all changes in files.
                // Then we re-queue the action to make sure that indirect invalidation happens,
                // then we commit the files again to apply the indirect changes
                // Commit(2) -> Requeue(2) -> Commit(1) -> Requeue(1)
                Commit(2);

                return(result);
            });
        }