From ca47896204482bf4a6979e3838bf7f09f61cebeb Mon Sep 17 00:00:00 2001
From: giy <giy@omp-system.ru>
Date: Fri, 02 Sep 2022 14:16:56 +0300
Subject: [PATCH] Обновление до версии 2.9.0

---
 QtVsTools.Package/QtMsBuild/QtProjectTracker.cs |  170 +++++++++++++++++---------------------------------------
 1 files changed, 51 insertions(+), 119 deletions(-)

diff --git a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
index 66db5c7..1d8e719 100644
--- a/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
+++ b/QtVsTools.Package/QtMsBuild/QtProjectTracker.cs
@@ -29,41 +29,41 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks.Dataflow;
-using Microsoft.Build.Evaluation;
-using Microsoft.Build.Framework;
 using Microsoft.VisualStudio.ProjectSystem;
 using Microsoft.VisualStudio.ProjectSystem.Properties;
+using Microsoft.VisualStudio.Shell;
 using Microsoft.VisualStudio.TaskStatusCenter;
 using Microsoft.VisualStudio.Threading;
-using EnvDTE;
+using Microsoft.VisualStudio.VCProjectEngine;
+
+using Task = System.Threading.Tasks.Task;
 
 namespace QtVsTools.QtMsBuild
 {
+    using Common;
     using Core;
     using VisualStudio;
-    using Thread = System.Threading.Thread;
+
     using SubscriberAction = ActionBlock<IProjectVersionedValue<IProjectSubscriptionUpdate>>;
 
     class QtProjectTracker : Concurrent<QtProjectTracker>
     {
-        static ConcurrentDictionary<string, QtProjectTracker> _Instances;
-        static ConcurrentDictionary<string, QtProjectTracker> Instances =>
-            StaticThreadSafeInit(() => _Instances, () =>
-                _Instances = new ConcurrentDictionary<string, QtProjectTracker>());
+        static LazyFactory StaticLazy { get; } = new LazyFactory();
 
-        static PunisherQueue<QtProjectTracker> _InitQueue;
-        static PunisherQueue<QtProjectTracker> InitQueue =>
-            StaticThreadSafeInit(() => _InitQueue, () =>
-                _InitQueue = new PunisherQueue<QtProjectTracker>());
+        static ConcurrentDictionary<string, QtProjectTracker> Instances => StaticLazy.Get(() =>
+            Instances, () => new ConcurrentDictionary<string, QtProjectTracker>());
 
-        static IVsTaskStatusCenterService _StatusCenter;
-        static IVsTaskStatusCenterService StatusCenter => StaticThreadSafeInit(() => _StatusCenter,
-                () => _StatusCenter = VsServiceProvider
-                    .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>());
+        static PunisherQueue<QtProjectTracker> InitQueue => StaticLazy.Get(() =>
+            InitQueue, () => new PunisherQueue<QtProjectTracker>());
+
+        static IVsTaskStatusCenterService StatusCenter => StaticLazy.Get(() =>
+            StatusCenter, () => VsServiceProvider
+                .GetService<SVsTaskStatusCenterService, IVsTaskStatusCenterService>());
 
         static Task InitDispatcher { get; set; }
         static ITaskHandler2 InitStatus { get; set; }
@@ -75,73 +75,37 @@
             Initialized = new EventWaitHandle(false, EventResetMode.ManualReset);
         }
 
-        class Subscriber : IDisposable
-        {
-            public Subscriber(QtProjectTracker tracker, ConfiguredProject config)
-            {
-                Tracker = tracker;
-                Config = config;
-                Subscription = Config.Services.ProjectSubscription.JointRuleSource.SourceBlock
-                    .LinkTo(new SubscriberAction(ProjectUpdateAsync),
-                        ruleNames: new[]
-                        {
-                            "ClCompile",
-                            "QtRule10_Settings",
-                            "QtRule30_Moc",
-                            "QtRule40_Rcc",
-                            "QtRule60_Repc",
-                            "QtRule50_Uic",
-                            "QtRule_Translation",
-                            "QtRule70_Deploy",
-                        },
-                        initialDataAsNew: false
-                    );
-            }
-
-            QtProjectTracker Tracker { get; set; }
-            ConfiguredProject Config { get; set; }
-            IDisposable Subscription { get; set; }
-
-            public void Dispose()
-            {
-                Subscription?.Dispose();
-                Subscription = null;
-            }
-
-            async Task ProjectUpdateAsync(IProjectVersionedValue<IProjectSubscriptionUpdate> update)
-            {
-                await Tracker.OnProjectUpdateAsync(Config, update.Value);
-            }
-        }
-
         public EnvDTE.Project Project { get; private set; }
+        public string ProjectPath { get; private set; }
+        public VCProject VcProject { get; private set; }
         public UnconfiguredProject UnconfiguredProject { get; private set; }
-        public EventWaitHandle Initialized { get; private set; }
-        List<Subscriber> Subscribers { get; set; }
+        public EventWaitHandle Initialized { get; }
 
-        public static bool IsTracked(EnvDTE.Project project)
+        public static bool IsTracked(string projectPath)
         {
-            return Instances.ContainsKey(project.FullName);
+            return Instances.ContainsKey(projectPath);
         }
 
         public static void Add(EnvDTE.Project project)
         {
             if (!QtVsToolsPackage.Instance.Options.ProjectTracking)
                 return;
-            Get(project);
+
+            ThreadHelper.ThrowIfNotOnUIThread();
+            Get(project, project.FullName);
         }
 
-        public static QtProjectTracker Get(EnvDTE.Project project)
+        public static QtProjectTracker Get(EnvDTE.Project project, string projectPath)
         {
             lock (StaticCriticalSection) {
-                QtProjectTracker tracker = null;
-                if (Instances.TryGetValue(project.FullName, out tracker))
+                if (Instances.TryGetValue(projectPath, out QtProjectTracker tracker))
                     return tracker;
                 tracker = new QtProjectTracker
                 {
                     Project = project,
+                    ProjectPath = projectPath
                 };
-                Instances[project.FullName] = tracker;
+                Instances[projectPath] = tracker;
                 InitQueue.Enqueue(tracker);
                 if (InitDispatcher == null)
                     InitDispatcher = Task.Run(InitDispatcherLoopAsync);
@@ -162,14 +126,17 @@
             while (!QtVsToolsPackage.Instance.Zombied) {
                 while (InitQueue.IsEmpty)
                     await Task.Delay(100);
-                QtProjectTracker tracker;
-                if (InitQueue.TryDequeue(out tracker)) {
+                if (InitQueue.TryDequeue(out QtProjectTracker tracker)) {
                     if (InitStatus == null) {
-                        await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync();
+                        await QtVsToolsPackage.Instance.JoinableTaskFactory
+                            .SwitchToMainThreadAsync();
                         tracker.BeginInitStatus();
                         await TaskScheduler.Default;
                     } else {
+                        await QtVsToolsPackage.Instance.JoinableTaskFactory
+                            .SwitchToMainThreadAsync();
                         tracker.UpdateInitStatus(0);
+                        await TaskScheduler.Default;
                     }
                     await tracker.InitializeAsync();
                 }
@@ -187,9 +154,12 @@
         async Task InitializeAsync()
         {
             int p = 0;
+            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
             UpdateInitStatus(p += 10);
 
-            await QtVsToolsPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync();
+            VcProject = Project.Object as VCProject;
+            if (VcProject == null)
+                return;
             UpdateInitStatus(p += 10);
 
             var context = Project.Object as IVsBrowseObjectContext;
@@ -211,57 +181,23 @@
 
             Initialized.Set();
 
-            Subscribers = new List<Subscriber>();
             int n = configs.Count;
             int d = (100 - p) / (n * 2);
             foreach (var config in configs) {
                 var configProject = await UnconfiguredProject.LoadConfiguredProjectAsync(config);
                 UpdateInitStatus(p += d);
-                Subscribers.Add(new Subscriber(this, configProject));
-                configProject.ProjectUnloading += OnProjectUnloading;
+                configProject.ProjectUnloading += OnProjectUnloadingAsync;
                 if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) {
                     Messages.Print(string.Format(
                         "{0:HH:mm:ss.FFF} QtProjectTracker({1}): Started tracking [{2}] {3}",
                         DateTime.Now, Thread.CurrentThread.ManagedThreadId,
-                        config.Name,
-                        UnconfiguredProject.FullPath));
+                        config.Name, ProjectPath));
                 }
                 UpdateInitStatus(p += d);
             }
         }
 
-
-        async Task OnProjectUpdateAsync(ConfiguredProject config, IProjectSubscriptionUpdate update)
-        {
-            var changes = update.ProjectChanges.Values
-                .Where(x => x.Difference.AnyChanges)
-                .Select(x => x.Difference);
-            var changesCount = changes
-                .Select(x => x.AddedItems.Count
-                    + x.ChangedItems.Count
-                    + x.ChangedProperties.Count
-                    + x.RemovedItems.Count
-                    + x.RenamedItems.Count)
-                .Sum();
-            var changedProps = changes.SelectMany(x => x.ChangedProperties);
-            if (changesCount == 0
-                || (changesCount == 1
-                    && changedProps.Count() == 1
-                    && changedProps.First() == "QtLastBackgroundBuild")) {
-                return;
-            }
-
-            if (QtVsToolsPackage.Instance.Options.BuildDebugInformation) {
-                Messages.Print(string.Format(
-                    "{0:HH:mm:ss.FFF} QtProjectTracker({1}): Changed [{2}] {3}",
-                    DateTime.Now, Thread.CurrentThread.ManagedThreadId,
-                    config.ProjectConfiguration.Name,
-                    config.UnconfiguredProject.FullPath));
-            }
-            await QtProjectIntellisense.RefreshAsync(Project, config.ProjectConfiguration.Name);
-        }
-
-        async Task OnProjectUnloading(object sender, EventArgs args)
+        async Task OnProjectUnloadingAsync(object sender, EventArgs args)
         {
             var project = sender as ConfiguredProject;
             if (project == null || project.Services == null)
@@ -274,18 +210,16 @@
                     project.UnconfiguredProject.FullPath));
             }
             lock (CriticalSection) {
-                if (Subscribers != null) {
-                    Subscribers.ForEach(s => s.Dispose());
-                    Subscribers.Clear();
-                    Subscribers = null;
-                }
-                project.ProjectUnloading -= OnProjectUnloading;
-                Instances.TryRemove(Project.FullName, out QtProjectTracker tracker);
+                project.ProjectUnloading -= OnProjectUnloadingAsync;
+                Instances.TryRemove(project.UnconfiguredProject.FullPath, out QtProjectTracker _);
             }
+            await Task.Yield();
         }
 
         void BeginInitStatus()
         {
+            ThreadHelper.ThrowIfNotOnUIThread();
+
             lock (StaticCriticalSection) {
                 if (InitStatus != null)
                     return;
@@ -303,9 +237,8 @@
                             PercentComplete = 0
                         })
                         as ITaskHandler2;
-                } catch (Exception e) {
-                    Messages.Print(
-                        e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
+                } catch (Exception exception) {
+                    exception.Log();
                 }
                 InitStatus.RegisterTask(new Task(() => throw new InvalidOperationException()));
             }
@@ -320,13 +253,12 @@
                     InitStatus.Progress.Report(new TaskProgressData
                     {
                         ProgressText = string.Format("{0} ({1} project(s) remaining)",
-                            Project.Name, InitQueue.Count),
+                            Path.GetFileNameWithoutExtension(ProjectPath), InitQueue.Count),
                         CanBeCanceled = true,
                         PercentComplete = percentComplete
                     });
-                } catch (Exception e) {
-                    Messages.Print(
-                        e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
+                } catch (Exception exception) {
+                    exception.Log();
                 }
             }
         }

--
Gitblit v1.9.1