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); }
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); }); } }
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); }); }
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 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); }); }
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); }); }
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); }); }
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); }); }
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); }); }
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); }
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); } }
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); // } }
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); }); }