Skip to content

Commit

Permalink
All migrated code compiles now.
Browse files Browse the repository at this point in the history
  • Loading branch information
menees committed Apr 25, 2020
1 parent 944bfaf commit 5484e0c
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 72 deletions.
18 changes: 1 addition & 17 deletions src/Menees.VsTools/MainPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public sealed partial class MainPackage : AsyncPackage, IDisposable
{
#region Private Data Members

private static MainPackage instance;
private static Options generalOptions;
private static BaseConverter.Options baseConverterOptions;

Expand Down Expand Up @@ -53,21 +52,6 @@ public MainPackage()

#region Internal Properties

internal static MainPackage Instance
{
get
{
ThreadHelper.ThrowIfNotOnUIThread();

if (instance == null)
{
ForceLoad();
}

return instance;
}
}

internal static Options GeneralOptions
{
get
Expand Down Expand Up @@ -196,7 +180,7 @@ protected override async System.Threading.Tasks.Task InitializeAsync(Cancellatio
LogMessage(string.Format("After {0}'s base.Initialize()", this.ToString()));

await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
instance = this;
ScanInfo.GetUserRegistryRoot = () => this.UserRegistryRoot;

// Ryan Molden from Microsoft says that GetDialogPage caches the result, so we're going to cache it too.
// I've also verified GetDialogPage's caching implementation in VS11 by looking at it with Reflector.
Expand Down
1 change: 1 addition & 0 deletions src/Menees.VsTools/Menees.VsTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
<Compile Include="StatisticsDialog.xaml.cs">
<DependentUpon>StatisticsDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Tasks\BackgroundOptions.cs" />
<Compile Include="Tasks\CommentTask.cs" />
<Compile Include="Tasks\CommentTaskProvider.cs" />
<Compile Include="Tasks\CommentToken.cs" />
Expand Down
66 changes: 66 additions & 0 deletions src/Menees.VsTools/Tasks/BackgroundOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace Menees.VsTools.Tasks
{
#region Using Directives

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

#endregion

internal sealed class BackgroundOptions
{
#region Private Data Members

private readonly object locker = new object();

#endregion

#region Public Events

public event EventHandler Updated;

#endregion

#region Public Properties

public bool EnableCommentScans { get; private set; }

public string ExcludeFromCommentScans { get; private set; }

#endregion

#region Public Methods

public bool Update(Options options)
{
bool updated = false;

lock (this.locker)
{
if (this.EnableCommentScans != options.EnableCommentScans)
{
this.EnableCommentScans = options.EnableCommentScans;
updated = true;
}

if (this.ExcludeFromCommentScans != options.ExcludeFromCommentScans)
{
this.ExcludeFromCommentScans = options.ExcludeFromCommentScans;
updated = true;
}
}

if (updated)
{
this.Updated?.Invoke(this, EventArgs.Empty);
}

return updated;
}

#endregion
}
}
80 changes: 41 additions & 39 deletions src/Menees.VsTools/Tasks/CommentTaskProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Menees.VsTools.Tasks
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.TextManager.Interop;
using Sys = System.Threading.Tasks;

#endregion

Expand All @@ -38,6 +39,7 @@ internal sealed class CommentTaskProvider : TaskProvider, IVsTaskListEvents
private readonly FileMonitor fileMonitor;
private readonly FileItemManager manager;
private readonly List<CommentToken> foregroundTokens = new List<CommentToken>();
private readonly BackgroundOptions backgroundOptions = new BackgroundOptions();

private bool disposed;
private int isBackgroundTimerExecuting;
Expand All @@ -55,7 +57,6 @@ public CommentTaskProvider(MainPackage package)
ThreadHelper.ThrowIfNotOnUIThread();

this.ServiceProvider = package.ServiceProvider;
MainPackage.GeneralOptions.Applied += this.Options_Applied;

// In some cases the task list may not be available (e.g., during devenv.exe /build).
if (!(this.ServiceProvider.GetService(typeof(SVsTaskList)) is IVsTaskList taskList))
Expand All @@ -64,6 +65,10 @@ public CommentTaskProvider(MainPackage package)
}
else
{
Options options = MainPackage.GeneralOptions;
options.Applied += this.Options_Applied;
this.backgroundOptions.Update(options);

// Register a custom category so Visual Studio will invoke our IVsTaskListEvents callbacks.
VSTASKCATEGORY[] assignedCategory = new VSTASKCATEGORY[1];
int hr = this.VsTaskList.RegisterCustomCategory(CategoryId, (uint)TaskCategory.Comments + 1, assignedCategory);
Expand All @@ -90,7 +95,7 @@ public CommentTaskProvider(MainPackage package)
this.solutionMonitor = new SolutionMonitor(this);
this.documentMonitor = new DocumentMonitor(this);
this.fileMonitor = new FileMonitor(this);
this.manager = new FileItemManager(this, this.fileMonitor, MainPackage.GeneralOptions);
this.manager = new FileItemManager(this, this.fileMonitor, this.backgroundOptions);

// Enable the timers last. The BackgroundTimerCallback will fire after ScanDelay (on a worker thread),
// so we have to ensure that everything is initialized before its first callback.
Expand Down Expand Up @@ -206,27 +211,11 @@ private void BackgroundTimerCallback(object state)
{
if (Interlocked.CompareExchange(ref this.isBackgroundTimerExecuting, 1, 0) == 0)
{
// TODO: Get rid of these nested if blocks that are just here to get things to compile. [Bill, 4/19/2020]
if (this.appliedOptionsPending)
{
this.appliedOptionsPending = false;
if (this.foregroundTokensChanged)
{
this.foregroundTokensChanged = false;
if (this.backgroundTokens == null)
{
this.backgroundTokens = new List<CommentToken>();
}
}
}

#if TODO // TODO: Rewrite this to work from a background thread. [Bill, 4/19/2020]
// Make sure only one thread at a time is running (in case this handler takes longer than the timer's interval).
// Make sure only one thread at a time is running (in case this handler takes longer than the timer's interval).
try
{
// TODO: Switch to UI thread (from BackgroundTimerCallback)? [Bill, 4/19/2020]
// If the user disables this in Options, then immediately stop scanning (without waiting for a restart).
if (MainPackage.GeneralOptions.EnableCommentScans)
if (this.backgroundOptions.EnableCommentScans)
{
bool updateAll = this.appliedOptionsPending;
this.appliedOptionsPending = false;
Expand All @@ -242,22 +231,10 @@ private void BackgroundTimerCallback(object state)

if (this.backgroundTokens.Count > 0 || updateAll)
{
IEnumerable<HierarchyItem> allHierarchyItems = this.solutionMonitor.GetChangedHierarchy();
if (allHierarchyItems != null)
{
Debug("Updating Hierarchy ({0})", allHierarchyItems.Count());
this.manager.UpdateHierarchy(allHierarchyItems);
}

IReadOnlyDictionary<string, DocumentItem> changedDocuments = this.documentMonitor.GetChangedDocuments();
if (changedDocuments != null)
{
Debug(
"Updating Documents ({0}): {1}",
changedDocuments.Count,
string.Join(", ", changedDocuments.Select(pair => Path.GetFileName(pair.Key) + '=' + (pair.Value != null))));
this.manager.UpdateDocuments(changedDocuments);
}
var foregroundUpdate = ThreadHelper.JoinableTaskFactory.RunAsync(this.ForegroundUpdateAsync);
#pragma warning disable VSTHRD102 // Implement internal logic asynchronously. Some of the VS calls must be made from the foreground thread.
foregroundUpdate.Join();
#pragma warning restore VSTHRD102 // Implement internal logic asynchronously

IReadOnlyDictionary<string, bool> changedFiles = this.fileMonitor.GetChangedFiles();
if (changedFiles != null)
Expand All @@ -284,7 +261,28 @@ private void BackgroundTimerCallback(object state)
{
Interlocked.Exchange(ref this.isBackgroundTimerExecuting, 0);
}
#endif
}
}

private async Sys.Task ForegroundUpdateAsync()
{
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

IEnumerable<HierarchyItem> allHierarchyItems = this.solutionMonitor.GetChangedHierarchy();
if (allHierarchyItems != null)
{
Debug("Updating Hierarchy ({0})", allHierarchyItems.Count());
this.manager.UpdateHierarchy(allHierarchyItems);
}

IReadOnlyDictionary<string, DocumentItem> changedDocuments = this.documentMonitor.GetChangedDocuments();
if (changedDocuments != null)
{
Debug(
"Updating Documents ({0}): {1}",
changedDocuments.Count,
string.Join(", ", changedDocuments.Select(pair => Path.GetFileName(pair.Key) + '=' + (pair.Value != null))));
this.manager.UpdateDocuments(changedDocuments);
}
}

Expand Down Expand Up @@ -337,9 +335,13 @@ private void CacheCommentTokens()

private void Options_Applied(object sender, EventArgs e)
{
this.appliedOptionsPending = true;
ThreadHelper.ThrowIfNotOnUIThread();
if (this.backgroundOptions.Update(MainPackage.GeneralOptions))
{
this.appliedOptionsPending = true;
}
}

#endregion
#endregion
}
}
4 changes: 0 additions & 4 deletions src/Menees.VsTools/Tasks/FileItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ internal sealed class FileItem

internal FileItem(CommentTaskProvider provider, string fileName)
{
ThreadHelper.ThrowIfNotOnUIThread();

// Note: The caller should check FileUtility.IsValidPath(fileName) before invoking this constructor.
this.provider = provider;
this.FileName = fileName;
Expand Down Expand Up @@ -85,8 +83,6 @@ public DocumentItem Document

set
{
ThreadHelper.ThrowIfNotOnUIThread();

if (this.document != value)
{
this.document = value;
Expand Down
9 changes: 4 additions & 5 deletions src/Menees.VsTools/Tasks/FileItemManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,20 @@ internal sealed class FileItemManager
private readonly Dictionary<string, FileItem> files = new Dictionary<string, FileItem>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<FileItem> changedItems = new HashSet<FileItem>();
private readonly Dictionary<CommentTask, bool> changedTasks = new Dictionary<CommentTask, bool>();
private readonly Options options;
private readonly BackgroundOptions options;
private readonly Dictionary<string, Regex> excludePatternsCache = new Dictionary<string, Regex>();
private readonly List<Regex> backgroundExcludePatterns = new List<Regex>();

#endregion

#region Constructors

public FileItemManager(CommentTaskProvider provider, FileMonitor monitor, Options options)
public FileItemManager(CommentTaskProvider provider, FileMonitor monitor, BackgroundOptions options)
{
this.provider = provider;
this.monitor = monitor;

this.options = options;
this.options.Applied += this.Options_Applied;
this.options.Updated += this.Options_Updated;
this.RefreshExcludePatterns();
}

Expand Down Expand Up @@ -296,7 +295,7 @@ private void RefreshItem(FileItem item, RefreshAction action)
}
}

private void Options_Applied(object sender, EventArgs e)
private void Options_Updated(object sender, EventArgs e)
{
this.RefreshExcludePatterns();
}
Expand Down
11 changes: 4 additions & 7 deletions src/Menees.VsTools/Tasks/ScanInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ private ScanInfo(IEnumerable<Delimiter> delimiters, IEnumerable<Language> langua

#region Public Properties

public static Func<RegistryKey> GetUserRegistryRoot { get; set; }

public bool IsScannable
{
get
Expand All @@ -90,8 +92,6 @@ public bool IsScannable

public static ScanInfo Get(FileItem file)
{
ThreadHelper.ThrowIfNotOnUIThread();

Cache cache = LazyCache.Value;
string extension = Path.GetExtension(file.FileName);
if (cache.TryGet(extension, out ScanInfo result))
Expand Down Expand Up @@ -217,7 +217,6 @@ private static ScanInfo Merge(ScanInfo scanInfo1, ScanInfo scanInfo2)

private static ScanInfo Infer(FileItem file, Cache cache)
{
ThreadHelper.ThrowIfNotOnUIThread();
ScanInfo result = Unscannable;

try
Expand Down Expand Up @@ -266,13 +265,11 @@ private static ScanInfo Infer(FileItem file, Cache cache)

private static bool TryGetCustomExtensionScanInfo(string extension, Cache cache, ref ScanInfo scanInfo)
{
ThreadHelper.ThrowIfNotOnUIThread();
bool result = false;

MainPackage package = MainPackage.Instance;
if (package != null && !string.IsNullOrEmpty(extension) && extension.Length > 1 && extension[0] == '.')
if (!string.IsNullOrEmpty(extension) && extension.Length > 1 && extension[0] == '.')
{
using (RegistryKey studioUserRoot = package.UserRegistryRoot)
using (RegistryKey studioUserRoot = GetUserRegistryRoot?.Invoke())
{
if (studioUserRoot != null)
{
Expand Down

0 comments on commit 5484e0c

Please sign in to comment.