public class UnityProfilerEventsHost()

in resharper/resharper-unity/src/Unity.Rider/Integration/Protocol/UnityProfilerEventsHost.cs [28:125]


public class UnityProfilerEventsHost(
    ILogger logger,
    ISolution solution,
    UnityProfilerInfoCollector unityProfilerInfoCollector,
    Lifetime componentLifetime)
{
    public void AdviseOpenFileByMethodName(UnityProfilerModel unityProfilerModel,
        FrontendBackendHost frontendBackendHost, Lifetime lifetime)
    {
        unityProfilerModel.OpenFileBySampleInfo.SetAsync((_, sampleStackInfo) =>
        {
            var result = new RdTask<Unit>();
            if (string.IsNullOrEmpty(sampleStackInfo.SampleStack) || string.IsNullOrEmpty(sampleStackInfo.SampleName))
                return result;

            using (ReadLockCookie.Create())
            {
                unityProfilerInfoCollector.OnOpenFileBySampleInfo();
                try
                {
                    NavigateToCode(sampleStackInfo.SampleStack);
                }
                catch (Exception e)
                {
                    logger.Error(e);
                    result.Set(Unit.Instance);
                }

                try
                {
                    ShowConsoleWithCallstack(frontendBackendHost, sampleStackInfo.SampleStack, sampleStackInfo.SampleName, lifetime);
                }
                catch (Exception e)
                {
                    logger.Error(e);
                    result.Set(Unit.Instance);
                }
            }

            return result;
        });
    }

    private void ShowConsoleWithCallstack(FrontendBackendHost frontendBackendHost, string sampleStack,
        string sampleName, Lifetime lifetime)
    {
        frontendBackendHost.Do(model => model.AllowSetForegroundWindow
            .Start(lifetime, Unit.Instance).Result
            .AdviseOnce(componentLifetime, _ => model.ActivateRider()));
        sampleStack = sampleStack.Replace("/", "\n");
        solution.GetComponent<RiderStackTraceHost>().ShowConsole(new StackTraceConsole(sampleName, sampleStack));
    }

    private void NavigateToCode(string profilerCallstack)
    {
        var stackTraceOptions = solution.GetComponent<StackTraceOptions>();
        var parser = new StackTraceParser(profilerCallstack, solution,
            solution.GetComponent<StackTracePathResolverCache>(), stackTraceOptions.GetState());

        try
        {
            var rootNode = parser.Parse(0, profilerCallstack.Length);
            IOccurrence? occurrence = null;

            //Attempting to get the most bottom node
            //callstack example:
            // PlayerLoop
            // |- Update.ScriptRunBehaviourUpdate
            // |-- BehaviourUpdate
            // |--- Assembly-CSharp.dll!MyNamespace1::HeavyScript1.Update() [Invoke]
            foreach (var nodeNode in rootNode.Nodes)
            {
                if (nodeNode is IdentifierNode identifierNode)
                {
                    var identifierNodeResolveState = identifierNode.ResolveState;

                    using (CompilationContextCookie.GetExplicitUniversalContextIfNotSet())
                    {
                        occurrence = identifierNodeResolveState.MainCandidate?
                            .GetNavigationDeclarations().FirstOrDefault() ?? occurrence;
                    }
                }
            }

            if (occurrence != null)
                occurrence.Navigate(solution,
                    solution.GetComponent<IMainWindowPopupWindowContext>().Source, true);
            else
            {
                logger.Verbose($"No occurrence found for '{profilerCallstack}'");
            }
        }
        catch (Exception e)
        {
            logger.LogException(e);
        }
    }
}