public class GodotTracker()

in resharper/src/ProjectModel/GodotTracker.cs [22:108]


    public class GodotTracker(
        ISolution solution,
        ILogger logger,
        ISolutionLoadTasksScheduler loadTasksScheduler,
        IShellLocks locks,
        Lifetime lifetime)
        : ISolutionLoadTasksInitialSynchronizeSolutionListener2
    {
        public VirtualFileSystemPath? MainProjectBasePath { get; private set; }
        public VirtualFileSystemPath? ProjectGodotPath { get; private set; }
        
        public IProject? MainProject { get; private set; }
        public GodotDescriptor? GodotDescriptor { get; private set; }

        IEnumerable<SolutionLoadTasksListenerExecutionStep> ISolutionLoadTasksInitialSynchronizeSolutionListener2.OnSolutionLoadInitialSynchronizeSolution(OuterLifetime loadLifetime)
        {
            var barrierCookie = loadTasksScheduler.SetTasksBarrier(GetType(), SolutionLoadTaskKinds.Done,
                "Waiting for Godot solution load tasks");
            locks.Tasks.StartNew(lifetime, Scheduling.FreeThreaded, TaskPriority.AboveNormal,  () =>
            {
                var model = solution.GetProtocolSolution().GetGodotFrontendBackendModel();
                try
                {
                    if (!solution.SolutionFilePath.IsEmpty)
                    {
                        var project = GetMainGodotProject();
                        if (project == null) return;
                        MainProject = project;
                        logger.Verbose($"Godot MainProjectBasePath: {MainProjectBasePath}");
                        GodotDescriptor = new GodotDescriptor(false, MainProjectBasePath!.FullPath, MainProject.ProjectFile?.Location?.FullPath,
                            MainProject.TargetFrameworkIds.SingleItem().ToRdTargetFrameworkInfo());

                    }
                    else
                    {
                        var files = solution.SolutionDirectory.GetChildFiles(3, "project.godot",
                            PathSearchFlags.RecurseIntoSubdirectories);
                        var bestMatch = files.OrderBy(it => it.Components.Count()).FirstOrDefault();
                        if (bestMatch == null) return;
                        GodotDescriptor = new GodotDescriptor(true, bestMatch.Directory.FullPath, null, null);
                        ProjectGodotPath = bestMatch;
                    }
                }
                finally
                {
                    barrierCookie.Dispose();
                    locks.ExecuteOrQueue("Sync Godot model", () =>
                    {
                        if (GodotDescriptor != null) 
                            model.GodotDescriptor.SetValue(GodotDescriptor);
                        model.IsGodotProject.SetValue(GodotDescriptor != null);
                    });
                }
            }).NoAwait();
            return EmptyList<SolutionLoadTasksListenerExecutionStep>.Enumerable;
        }

        private IProject? GetMainGodotProject()
        {
            using (ReadLockCookie.Create())
            {
                foreach (var project in solution.GetAllProjects())
                {
                    if (project.ProjectFile == null) continue; // MiscProject and SolutionProject
                    // not a regular generated project, however can happen with gdextensions template
                    var subItem = project.GetSubItems("project.godot").FirstOrDefault();
                    if (subItem != null)
                    {
                        ProjectGodotPath = subItem.Location;
                        MainProjectBasePath = ProjectGodotPath.Parent;
                        return project;
                    }

                    // regular case
                    var file = project.Location.Combine("project.godot");
                    if (file.ExistsFile)
                    {
                        ProjectGodotPath = file;
                        MainProjectBasePath = project.Location;
                        return project;
                    }
                }
            }

            return null;
        }
    }