diff --git a/src/EditorFeatures/Core/Shared/Preview/PreviewSolutionCrawlerRegistrationService.cs b/src/EditorFeatures/Core/Shared/Preview/PreviewSolutionCrawlerRegistrationService.cs
index d99a98d12116880bb603f2ad98dc85b5fe2d6ce4..c6cdfe76b04f8b69d44137ba2ba11913793fa59e 100644
--- a/src/EditorFeatures/Core/Shared/Preview/PreviewSolutionCrawlerRegistrationService.cs
+++ b/src/EditorFeatures/Core/Shared/Preview/PreviewSolutionCrawlerRegistrationService.cs
@@ -31,7 +31,7 @@ public async void Register(Workspace workspace)
{
try
{
- var workerBackOffTimeSpanInMS = workspace.Options.GetOption(SolutionCrawlerOptions.PreviewBackOffTimeSpanInMS);
+ var workerBackOffTimeSpanInMS = workspace.Options.GetOption(InternalSolutionCrawlerOptions.PreviewBackOffTimeSpanInMS);
var analyzer = _provider.CreateIncrementalAnalyzer(workspace);
var source = s_cancellationTokens.GetValue(workspace, _ => new CancellationTokenSource());
diff --git a/src/EditorFeatures/Test/MinimalTestExportProvider.cs b/src/EditorFeatures/Test/MinimalTestExportProvider.cs
index 3eba02338ca53ca66c06e60a5acbb02c6edca10c..2f22d27cc5dccb08b726f608b64d43d6473395be 100644
--- a/src/EditorFeatures/Test/MinimalTestExportProvider.cs
+++ b/src/EditorFeatures/Test/MinimalTestExportProvider.cs
@@ -56,7 +56,7 @@ public static Type[] GetLanguageNeutralTypes()
typeof(TestExportProvider)
};
- return types.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(SolutionCrawlerOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
+ return types.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(InternalSolutionCrawlerOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(EditorComponentOnOffOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(ServiceComponentOnOffOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
.Concat(TestHelpers.GetAllTypesWithStaticFieldsImplementingType(typeof(Microsoft.CodeAnalysis.Formatting.FormattingOptions).Assembly, typeof(Microsoft.CodeAnalysis.Options.IOption)))
diff --git a/src/Features/Core/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs b/src/Features/Core/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs
index f057c9ee07cfa4099e7a5e3606a664cd89ec7aad..a2526b9fbe2763201322f95af6a4e51a0f1830dd 100644
--- a/src/Features/Core/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs
+++ b/src/Features/Core/Diagnostics/EngineV1/DiagnosticIncrementalAnalyzer_GetDiagnostics.cs
@@ -458,6 +458,8 @@ public async Task ReanalyzeAllDocumentsAsync(Project project, CancellationToken
{
foreach (var document in project.Documents)
{
+ cancellationToken.ThrowIfCancellationRequested();
+
await AppendDiagnosticsAsync(document, cancellationToken).ConfigureAwait(false);
}
}
diff --git a/src/Features/Core/Features.csproj b/src/Features/Core/Features.csproj
index 406707ae0e2e560d203f8216898c97071ff51508..eb93e9ada32f5f6a72dfa77acb4cea09a0c4dfb0 100644
--- a/src/Features/Core/Features.csproj
+++ b/src/Features/Core/Features.csproj
@@ -508,7 +508,7 @@
-
+
diff --git a/src/Features/Core/SolutionCrawler/IdleProcessor.cs b/src/Features/Core/SolutionCrawler/IdleProcessor.cs
index be7ae42f1e46557b0e177b8d208c6ba067dc9ca8..084f4f1b1ec18d777a22170acdfac1142766a58e 100644
--- a/src/Features/Core/SolutionCrawler/IdleProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/IdleProcessor.cs
@@ -51,6 +51,27 @@ protected void UpdateLastAccessTime()
_lastAccessTimeInMS = Environment.TickCount;
}
+ protected async Task WaitForIdleAsync()
+ {
+ while (true)
+ {
+ if (this.CancellationToken.IsCancellationRequested)
+ {
+ return;
+ }
+
+ var diffInMS = Environment.TickCount - _lastAccessTimeInMS;
+ if (diffInMS >= _backOffTimeSpanInMS)
+ {
+ return;
+ }
+
+ // TODO: will safestart/unwarp capture cancellation exception?
+ var timeLeft = _backOffTimeSpanInMS - diffInMS;
+ await Task.Delay(Math.Max(MinimumDelayInMS, timeLeft), this.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
+ }
+ }
+
private async Task ProcessAsync()
{
while (true)
@@ -80,27 +101,6 @@ private async Task ProcessAsync()
}
}
- private async Task WaitForIdleAsync()
- {
- while (true)
- {
- if (this.CancellationToken.IsCancellationRequested)
- {
- return;
- }
-
- var diffInMS = Environment.TickCount - _lastAccessTimeInMS;
- if (diffInMS >= _backOffTimeSpanInMS)
- {
- return;
- }
-
- // TODO: will safestart/unwarp capture cancellation exception?
- var timeLeft = _backOffTimeSpanInMS - diffInMS;
- await Task.Delay(Math.Max(MinimumDelayInMS, timeLeft), this.CancellationToken).ConfigureAwait(continueOnCapturedContext: false);
- }
- }
-
public virtual Task AsyncProcessorTask
{
get
diff --git a/src/Features/Core/SolutionCrawler/SolutionCrawlerOptions.cs b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
similarity index 55%
rename from src/Features/Core/SolutionCrawler/SolutionCrawlerOptions.cs
rename to src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
index f559cfb3cfef2b51828b0d494398e63c31fbf730..2ae33a367059ef13d03a0fcb068ebe4c95210c2a 100644
--- a/src/Features/Core/SolutionCrawler/SolutionCrawlerOptions.cs
+++ b/src/Features/Core/SolutionCrawler/InternalSolutionCrawlerOptions.cs
@@ -4,27 +4,29 @@
namespace Microsoft.CodeAnalysis.SolutionCrawler
{
- internal static class SolutionCrawlerOptions
+ internal static class InternalSolutionCrawlerOptions
{
+ public const string OptionName = "SolutionCrawler";
+
[ExportOption]
public static readonly Option SolutionCrawler = new Option("FeatureManager/Components", "Solution Crawler", defaultValue: true);
[ExportOption]
- public static readonly Option ActiveFileWorkerBackOffTimeSpanInMS = new Option("SolutionCrawler", "Active file worker backoff timespan in ms", defaultValue: 200);
+ public static readonly Option ActiveFileWorkerBackOffTimeSpanInMS = new Option(OptionName, "Active file worker backoff timespan in ms", defaultValue: 200);
[ExportOption]
- public static readonly Option AllFilesWorkerBackOffTimeSpanInMS = new Option("SolutionCrawler", "All files worker backoff timespan in ms", defaultValue: 1500);
+ public static readonly Option AllFilesWorkerBackOffTimeSpanInMS = new Option(OptionName, "All files worker backoff timespan in ms", defaultValue: 1500);
[ExportOption]
- public static readonly Option EntireProjectWorkerBackOffTimeSpanInMS = new Option("SolutionCrawler", "Entire project analysis worker backoff timespan in ms", defaultValue: 5000);
+ public static readonly Option EntireProjectWorkerBackOffTimeSpanInMS = new Option(OptionName, "Entire project analysis worker backoff timespan in ms", defaultValue: 5000);
[ExportOption]
- public static readonly Option SemanticChangeBackOffTimeSpanInMS = new Option("SolutionCrawler", "Semantic change backoff timespan in ms", defaultValue: 100);
+ public static readonly Option SemanticChangeBackOffTimeSpanInMS = new Option(OptionName, "Semantic change backoff timespan in ms", defaultValue: 100);
[ExportOption]
- public static readonly Option ProjectPropagationBackOffTimeSpanInMS = new Option("SolutionCrawler", "Project propagation backoff timespan in ms", defaultValue: 500);
+ public static readonly Option ProjectPropagationBackOffTimeSpanInMS = new Option(OptionName, "Project propagation backoff timespan in ms", defaultValue: 500);
[ExportOption]
- public static readonly Option PreviewBackOffTimeSpanInMS = new Option("SolutionCrawler", "Preview backoff timespan in ms", defaultValue: 500);
+ public static readonly Option PreviewBackOffTimeSpanInMS = new Option(OptionName, "Preview backoff timespan in ms", defaultValue: 500);
}
}
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncDocumentWorkItemQueue.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncDocumentWorkItemQueue.cs
index 7c571643ab839c1ab03a8f35e330cc345e843955..772e19a3a3c828340cb11d1352e8b529488fdbe1 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncDocumentWorkItemQueue.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncDocumentWorkItemQueue.cs
@@ -50,7 +50,7 @@ protected override bool TryTake_NoLock(DocumentId key, out WorkItem workInfo)
return false;
}
- protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out WorkItem workItem)
+ protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, ProjectDependencyGraph dependencyGraph, out WorkItem workItem)
{
// there must be at least one item in the map when this is called unless host is shutting down.
if (_documentWorkQueue.Count == 0)
@@ -59,7 +59,7 @@ protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out
return false;
}
- var documentId = GetBestDocumentId_NoLock(preferableProjectId);
+ var documentId = GetBestDocumentId_NoLock(preferableProjectId, dependencyGraph);
if (TryTake_NoLock(documentId, out workItem))
{
return true;
@@ -68,18 +68,9 @@ protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out
return Contract.FailWithReturn("how?");
}
- private DocumentId GetBestDocumentId_NoLock(ProjectId preferableProjectId)
+ private DocumentId GetBestDocumentId_NoLock(ProjectId preferableProjectId, ProjectDependencyGraph dependencyGraph)
{
- var projectId = preferableProjectId;
- if (projectId == null || !_documentWorkQueue.ContainsKey(projectId))
- {
- // explicitly iterate so that we can use struct enumerator
- foreach (var pair in _documentWorkQueue)
- {
- projectId = pair.Key;
- break;
- }
- }
+ var projectId = GetBestProjectId_NoLock(preferableProjectId, dependencyGraph);
var documentMap = _documentWorkQueue[projectId];
@@ -104,6 +95,35 @@ private DocumentId GetBestDocumentId_NoLock(ProjectId preferableProjectId)
return lowPriorityDocumentId;
}
+ private ProjectId GetBestProjectId_NoLock(ProjectId projectId, ProjectDependencyGraph dependencyGraph)
+ {
+ if (projectId != null)
+ {
+ if (_documentWorkQueue.ContainsKey(projectId))
+ {
+ return projectId;
+ }
+
+ // see if there is any project that depends on this project has work item queued. if there is any, use that project
+ // as next project to process
+ foreach (var dependingProjectId in dependencyGraph.GetProjectsThatDirectlyDependOnThisProject(projectId))
+ {
+ if (_documentWorkQueue.ContainsKey(dependingProjectId))
+ {
+ return dependingProjectId;
+ }
+ }
+ }
+
+ // explicitly iterate so that we can use struct enumerator
+ foreach (var pair in _documentWorkQueue)
+ {
+ return pair.Key;
+ }
+
+ return Contract.FailWithReturn("Shouldn't reach here");
+ }
+
protected override bool AddOrReplace_NoLock(WorkItem item)
{
// now document work
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncProjectWorkItemQueue.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncProjectWorkItemQueue.cs
index 8f81ac09930bda434b3389443ea952818b3b93b8..6b2f5ae5447921a8614557cefe7fe901fe2dd7c2 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncProjectWorkItemQueue.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncProjectWorkItemQueue.cs
@@ -49,7 +49,7 @@ protected override bool TryTake_NoLock(ProjectId key, out WorkItem workInfo)
return _projectWorkQueue.Remove(key);
}
- protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out WorkItem workItem)
+ protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, ProjectDependencyGraph dependencyGraph, out WorkItem workItem)
{
if (preferableProjectId != null)
{
@@ -57,6 +57,14 @@ protected override bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out
{
return true;
}
+
+ foreach (var dependingProjectId in dependencyGraph.GetProjectsThatDirectlyDependOnThisProject(preferableProjectId))
+ {
+ if (TryTake_NoLock(dependingProjectId, out workItem))
+ {
+ return true;
+ }
+ }
}
// explicitly iterate so that we can use struct enumerator
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs
index 0567e0022a975fed9d0b53addc934decc4f8c1b1..e0138bf04dea903f75e7cf39c3fa6267bed6ac7e 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.AsyncWorkItemQueue.cs
@@ -39,7 +39,7 @@ public AsyncWorkItemQueue(SolutionCrawlerProgressReporter progressReporter)
protected abstract bool TryTake_NoLock(TKey key, out WorkItem workInfo);
- protected abstract bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, out WorkItem workItem);
+ protected abstract bool TryTakeAnyWork_NoLock(ProjectId preferableProjectId, ProjectDependencyGraph dependencyGraph, out WorkItem workItem);
public bool HasAnyWork
{
@@ -52,17 +52,6 @@ public bool HasAnyWork
}
}
- public int WorkItemCount
- {
- get
- {
- lock (_gate)
- {
- return WorkItemCount_NoLock;
- }
- }
- }
-
public void RemoveCancellationSource(object key)
{
lock (_gate)
@@ -198,12 +187,12 @@ public bool TryTake(TKey key, out WorkItem workInfo, out CancellationTokenSource
}
}
- public bool TryTakeAnyWork(ProjectId preferableProjectId, out WorkItem workItem, out CancellationTokenSource source)
+ public bool TryTakeAnyWork(ProjectId preferableProjectId, ProjectDependencyGraph dependencyGraph, out WorkItem workItem, out CancellationTokenSource source)
{
lock (_gate)
{
// there must be at least one item in the map when this is called unless host is shutting down.
- if (TryTakeAnyWork_NoLock(preferableProjectId, out workItem))
+ if (TryTakeAnyWork_NoLock(preferableProjectId, dependencyGraph, out workItem))
{
if (!HasAnyWork_NoLock)
{
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.GlobalOperationAwareIdleProcessor.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.GlobalOperationAwareIdleProcessor.cs
index 7cc539b5c64fa6b91aeeb7ab4a99855a4da817fa..115d4832d2865d9b935193693184c004117a342a 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.GlobalOperationAwareIdleProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.GlobalOperationAwareIdleProcessor.cs
@@ -45,6 +45,14 @@ private abstract class GlobalOperationAwareIdleProcessor : IdleProcessor
_globalOperationNotificationService.Stopped += OnGlobalOperationStopped;
}
+ protected Task GlobalOperationTask
+ {
+ get
+ {
+ return _globalOperationTask;
+ }
+ }
+
protected abstract void PauseOnGlobalOperation();
private void OnGlobalOperationStarted(object sender, EventArgs e)
@@ -76,10 +84,30 @@ private void OnGlobalOperationStopped(object sender, GlobalOperationEventArgs e)
_globalOperationTask = SpecializedTasks.EmptyTask;
}
- protected async Task GlobalOperationWaitAsync()
+ protected abstract Task HigherQueueOperationTask { get; }
+ protected abstract bool HigherQueueHasWorkItem { get; }
+
+ protected async Task WaitForHigherPriorityOperationsAsync()
{
- // we wait for global operation if there is anything going on
- await _globalOperationTask.ConfigureAwait(false);
+ do
+ {
+ // we wait for global operation and higher queue operation if there is anything going on
+ if (!this.GlobalOperationTask.IsCompleted || !this.HigherQueueOperationTask.IsCompleted)
+ {
+ await Task.WhenAll(this.GlobalOperationTask, this.HigherQueueOperationTask).ConfigureAwait(false);
+ }
+
+ // if there are no more work left for higher queue, then it is our time to go ahead
+ if (!HigherQueueHasWorkItem)
+ {
+ break;
+ }
+
+ // back off and wait for next time slot.
+ this.UpdateLastAccessTime();
+ await this.WaitForIdleAsync().ConfigureAwait(false);
+ }
+ while (true);
}
public virtual void Shutdown()
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.HighPriorityProcessor.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.HighPriorityProcessor.cs
index 2d7f07cbffc777ddb100eb38fe1a31dc59fcc814..621e2ecdf9e0f66898710f7c2ffcac0c5a575129 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.HighPriorityProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.HighPriorityProcessor.cs
@@ -59,6 +59,14 @@ public Task Running
}
}
+ public bool HasAnyWork
+ {
+ get
+ {
+ return _workItemQueue.HasAnyWork;
+ }
+ }
+
public void Enqueue(WorkItem item)
{
Contract.ThrowIfFalse(item.DocumentId != null, "can only enqueue a document work item");
@@ -134,6 +142,7 @@ protected override async Task ExecuteAsync()
private bool GetNextWorkItem(out WorkItem workItem, out CancellationTokenSource documentCancellation)
{
+ // GetNextWorkItem since it can't fail. we still return bool to confirm that this never fail.
var documentId = _processor._documentTracker.GetActiveDocument();
if (documentId != null)
{
@@ -143,7 +152,11 @@ private bool GetNextWorkItem(out WorkItem workItem, out CancellationTokenSource
}
}
- return _workItemQueue.TryTakeAnyWork(preferableProjectId: null, workItem: out workItem, source: out documentCancellation);
+ return _workItemQueue.TryTakeAnyWork(
+ preferableProjectId: null,
+ dependencyGraph: this._processor.DependencyGraph,
+ workItem: out workItem,
+ source: out documentCancellation);
}
private async Task ProcessDocumentAsync(Solution solution, ImmutableArray analyzers, WorkItem workItem, CancellationTokenSource source)
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs
index 4108712287a10bd3ee3ec446ff821ad42e8bea72..5036b5dd47337fe78df926e890cb61e31a164047 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.IncrementalAnalyzerProcessor.cs
@@ -143,6 +143,14 @@ private Solution CurrentSolution
}
}
+ private ProjectDependencyGraph DependencyGraph
+ {
+ get
+ {
+ return CurrentSolution.GetProjectDependencyGraph();
+ }
+ }
+
private IEnumerable GetOpenDocumentIds()
{
return _registration.Workspace.GetOpenDocumentIds();
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.LowPriorityProcessor.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.LowPriorityProcessor.cs
index e989c6ce3852209dc853dc55b52e154be4d94537..2ca9a92ad72b85973c81c39ad007f0b50339fb2b 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.LowPriorityProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.LowPriorityProcessor.cs
@@ -57,15 +57,12 @@ protected override async Task ExecuteAsync()
try
{
// we wait for global operation, higher and normal priority processor to finish its working
- await Task.WhenAll(
- this.Processor._highPriorityProcessor.Running,
- this.Processor._normalPriorityProcessor.Running,
- GlobalOperationWaitAsync()).ConfigureAwait(false);
+ await WaitForHigherPriorityOperationsAsync().ConfigureAwait(false);
// process any available project work, preferring the active project.
WorkItem workItem;
CancellationTokenSource projectCancellation;
- if (_workItemQueue.TryTakeAnyWork(this.Processor.GetActiveProject(), out workItem, out projectCancellation))
+ if (_workItemQueue.TryTakeAnyWork(this.Processor.GetActiveProject(), this.Processor.DependencyGraph, out workItem, out projectCancellation))
{
await ProcessProjectAsync(this.Analyzers, workItem, projectCancellation).ConfigureAwait(false);
}
@@ -76,6 +73,22 @@ protected override async Task ExecuteAsync()
}
}
+ protected override Task HigherQueueOperationTask
+ {
+ get
+ {
+ return Task.WhenAll(this.Processor._highPriorityProcessor.Running, this.Processor._normalPriorityProcessor.Running);
+ }
+ }
+
+ protected override bool HigherQueueHasWorkItem
+ {
+ get
+ {
+ return this.Processor._highPriorityProcessor.HasAnyWork || this.Processor._normalPriorityProcessor.HasAnyWork;
+ }
+ }
+
protected override void PauseOnGlobalOperation()
{
_workItemQueue.RequestCancellationOnRunningTasks();
@@ -90,11 +103,25 @@ public void Enqueue(WorkItem item)
var added = _workItemQueue.AddOrReplace(item);
+ // lower priority queue gets lowest time slot possible. if there is any activity going on in higher queue, it drop whatever it has
+ // and let higher work item run
+ CancelRunningTaskIfHigherQueueHasWorkItem();
+
Logger.Log(FunctionId.WorkCoordinator_Project_Enqueue, s_enqueueLogger, Environment.TickCount, item.ProjectId, !added);
SolutionCrawlerLogger.LogWorkItemEnqueue(this.Processor._logAggregator, item.ProjectId);
}
+ private void CancelRunningTaskIfHigherQueueHasWorkItem()
+ {
+ if (!HigherQueueHasWorkItem)
+ {
+ return;
+ }
+
+ _workItemQueue.RequestCancellationOnRunningTasks();
+ }
+
private async Task ProcessProjectAsync(ImmutableArray analyzers, WorkItem workItem, CancellationTokenSource source)
{
if (this.CancellationToken.IsCancellationRequested)
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.NormalPriorityProcessor.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.NormalPriorityProcessor.cs
index 3c46bf2a33b6bcb15fdfa99a197552390836d39f..025f9afc0c336a93f7cdee8297a9643285640ccf 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.NormalPriorityProcessor.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.NormalPriorityProcessor.cs
@@ -124,6 +124,14 @@ public Task Running
}
}
+ public bool HasAnyWork
+ {
+ get
+ {
+ return _workItemQueue.HasAnyWork;
+ }
+ }
+
protected override async Task ExecuteAsync()
{
if (this.CancellationToken.IsCancellationRequested)
@@ -137,11 +145,7 @@ protected override async Task ExecuteAsync()
// mark it as running
_running = source.Task;
- // we wait for global operation if there is anything going on
- await GlobalOperationWaitAsync().ConfigureAwait(false);
-
- // we wait for higher processor to finish its working
- await this.Processor._highPriorityProcessor.Running.ConfigureAwait(false);
+ await WaitForHigherPriorityOperationsAsync().ConfigureAwait(false);
// okay, there must be at least one item in the map
await ResetStatesAsync().ConfigureAwait(false);
@@ -155,7 +159,7 @@ protected override async Task ExecuteAsync()
// process one of documents remaining
var documentCancellation = default(CancellationTokenSource);
WorkItem workItem;
- if (!_workItemQueue.TryTakeAnyWork(_currentProjectProcessing, out workItem, out documentCancellation))
+ if (!_workItemQueue.TryTakeAnyWork(_currentProjectProcessing, this.Processor.DependencyGraph, out workItem, out documentCancellation))
{
return;
}
@@ -183,6 +187,22 @@ protected override async Task ExecuteAsync()
}
}
+ protected override Task HigherQueueOperationTask
+ {
+ get
+ {
+ return this.Processor._highPriorityProcessor.Running;
+ }
+ }
+
+ protected override bool HigherQueueHasWorkItem
+ {
+ get
+ {
+ return this.Processor._highPriorityProcessor.HasAnyWork;
+ }
+ }
+
protected override void PauseOnGlobalOperation()
{
_workItemQueue.RequestCancellationOnRunningTasks();
diff --git a/src/Features/Core/SolutionCrawler/WorkCoordinator.cs b/src/Features/Core/SolutionCrawler/WorkCoordinator.cs
index a10bc9a9380967f31e55b3d952f44ba55e8b294a..07980da0e51107523924a744105e1a5ac19986a9 100644
--- a/src/Features/Core/SolutionCrawler/WorkCoordinator.cs
+++ b/src/Features/Core/SolutionCrawler/WorkCoordinator.cs
@@ -54,21 +54,21 @@ private partial class WorkCoordinator
_eventProcessingQueue = new SimpleTaskQueue(TaskScheduler.Default);
- var activeFileBackOffTimeSpanInMS = _optionService.GetOption(SolutionCrawlerOptions.ActiveFileWorkerBackOffTimeSpanInMS);
- var allFilesWorkerBackOffTimeSpanInMS = _optionService.GetOption(SolutionCrawlerOptions.AllFilesWorkerBackOffTimeSpanInMS);
- var entireProjectWorkerBackOffTimeSpanInMS = _optionService.GetOption(SolutionCrawlerOptions.EntireProjectWorkerBackOffTimeSpanInMS);
+ var activeFileBackOffTimeSpanInMS = _optionService.GetOption(InternalSolutionCrawlerOptions.ActiveFileWorkerBackOffTimeSpanInMS);
+ var allFilesWorkerBackOffTimeSpanInMS = _optionService.GetOption(InternalSolutionCrawlerOptions.AllFilesWorkerBackOffTimeSpanInMS);
+ var entireProjectWorkerBackOffTimeSpanInMS = _optionService.GetOption(InternalSolutionCrawlerOptions.EntireProjectWorkerBackOffTimeSpanInMS);
_documentAndProjectWorkerProcessor = new IncrementalAnalyzerProcessor(
listener, analyzerProviders, _registration,
activeFileBackOffTimeSpanInMS, allFilesWorkerBackOffTimeSpanInMS, entireProjectWorkerBackOffTimeSpanInMS, _shutdownToken);
- var semanticBackOffTimeSpanInMS = _optionService.GetOption(SolutionCrawlerOptions.SemanticChangeBackOffTimeSpanInMS);
- var projectBackOffTimeSpanInMS = _optionService.GetOption(SolutionCrawlerOptions.ProjectPropagationBackOffTimeSpanInMS);
+ var semanticBackOffTimeSpanInMS = _optionService.GetOption(InternalSolutionCrawlerOptions.SemanticChangeBackOffTimeSpanInMS);
+ var projectBackOffTimeSpanInMS = _optionService.GetOption(InternalSolutionCrawlerOptions.ProjectPropagationBackOffTimeSpanInMS);
_semanticChangeProcessor = new SemanticChangeProcessor(listener, _registration, _documentAndProjectWorkerProcessor, semanticBackOffTimeSpanInMS, projectBackOffTimeSpanInMS, _shutdownToken);
// if option is on
- if (_optionService.GetOption(SolutionCrawlerOptions.SolutionCrawler))
+ if (_optionService.GetOption(InternalSolutionCrawlerOptions.SolutionCrawler))
{
_registration.Workspace.WorkspaceChanged += OnWorkspaceChanged;
_registration.Workspace.DocumentOpened += OnDocumentOpened;
@@ -116,7 +116,7 @@ public void Shutdown(bool blockingShutdown)
private void OnOptionChanged(object sender, OptionChangedEventArgs e)
{
// if solution crawler got turned off or on.
- if (e.Option == SolutionCrawlerOptions.SolutionCrawler)
+ if (e.Option == InternalSolutionCrawlerOptions.SolutionCrawler)
{
var value = (bool)e.Value;
if (value)
diff --git a/src/Test/Diagnostics/DiagnosticOnly_Logger.cs b/src/Test/Diagnostics/DiagnosticOnly_Logger.cs
index d120cd0aa9c47948121c6753d8ede2b8a8c276fd..41702beebd081d2078d2e009590955272b6cf2d3 100644
--- a/src/Test/Diagnostics/DiagnosticOnly_Logger.cs
+++ b/src/Test/Diagnostics/DiagnosticOnly_Logger.cs
@@ -52,20 +52,6 @@ internal static void SetLogger(IOptionService optionsService, string loggerName)
Logger.SetLogger(GetLogger(optionsService, loggerName));
}
- ///
- /// let ones such as Perf setup to share loggingChecker func
- ///
- internal static Func GetLoggingChecker(IOptionService optionsService)
- {
- var functionIds = Enum.GetValues(typeof(FunctionId)).Cast();
- var functionIdOptions = functionIds.ToDictionary(
- id => id, id => optionsService.GetOption(FunctionIdOptions.GetOption(id)));
-
- Func loggingChecker = (functionId) => functionIdOptions[functionId];
-
- return loggingChecker;
- }
-
///
/// get string representation of functionId
///
@@ -109,9 +95,9 @@ private static ILogger GetLogger(IOptionService optionsService, string loggerNam
switch (loggerName)
{
case "EtwLogger":
- return new EtwLogger(GetLoggingChecker(optionsService));
+ return new EtwLogger(Logger.GetLoggingChecker(optionsService));
case "TraceLogger":
- return new TraceLogger(GetLoggingChecker(optionsService));
+ return new TraceLogger(Logger.GetLoggingChecker(optionsService));
default:
return EmptyLogger.Instance;
}
diff --git a/src/VisualStudio/Core/Def/Guids.cs b/src/VisualStudio/Core/Def/Guids.cs
index e6a2be85256b16323528149d85ea97967bc03364..e95c857f7ce183d5cefb79ce58f5c4adadfad84d 100644
--- a/src/VisualStudio/Core/Def/Guids.cs
+++ b/src/VisualStudio/Core/Def/Guids.cs
@@ -90,6 +90,7 @@ internal static class Guids
public const string RoslynOptionPagePerformanceFunctionIdIdString = "0C537218-3BDD-4CC8-AC4B-CEC152D4871A";
public const string RoslynOptionPagePerformanceLoggersIdString = "236AC96F-A60D-4BD6-A480-D315151EDC2B";
public const string RoslynOptionPageInternalDiagnosticsIdString = "48993C4C-C619-42AD-B1C8-79378AD8BEF2";
+ public const string RoslynOptionPageInternalSolutionCrawlerIdString = "9702D3BD-F06C-4A6A-974B-7D0C2BC89A72";
public static readonly Guid RoslynPackageId = new Guid(RoslynPackageIdString);
public static readonly Guid RoslynCommandSetId = new Guid(RoslynCommandSetIdString);
diff --git a/src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs b/src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs
index 78a55e8143bb5cd99eed49f70886a291f0fc86eb..3183669963bf36835fdabea035ab5e817ea7d837 100644
--- a/src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs
+++ b/src/VisualStudio/Core/Impl/Options/AbstractOptionPageControl.cs
@@ -60,6 +60,30 @@ protected void BindToOption(CheckBox checkbox, PerLanguageOption optionKey
_bindingExpressions.Add(bindingExpression);
}
+ protected void BindToOption(TextBox textBox, Option optionKey)
+ {
+ Binding binding = new Binding();
+
+ binding.Source = new OptionBinding(OptionService, optionKey);
+ binding.Path = new PropertyPath("Value");
+ binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
+
+ var bindingExpression = textBox.SetBinding(TextBox.TextProperty, binding);
+ _bindingExpressions.Add(bindingExpression);
+ }
+
+ protected void BindToOption(TextBox textBox, PerLanguageOption optionKey, string languageName)
+ {
+ Binding binding = new Binding();
+
+ binding.Source = new PerLanguageOptionBinding(OptionService, optionKey, languageName);
+ binding.Path = new PropertyPath("Value");
+ binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
+
+ var bindingExpression = textBox.SetBinding(TextBox.TextProperty, binding);
+ _bindingExpressions.Add(bindingExpression);
+ }
+
internal virtual void LoadSettings()
{
foreach (var bindingExpression in _bindingExpressions)
diff --git a/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs b/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs
index 8549447aaa5e69102120ff60c95353b17e46b865..bcd282f6fe838993a08b3db1b944d224c0ad6b44 100644
--- a/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs
+++ b/src/VisualStudio/Core/Impl/Options/AbstractSettingStoreOptionSerializer.cs
@@ -25,6 +25,16 @@ public AbstractSettingStoreOptionSerializer(IServiceProvider serviceProvider)
}
public virtual bool TryFetch(OptionKey optionKey, out object value)
+ {
+ return TryFetch(optionKey, (r, k, o) => r.GetValue(k, defaultValue: (bool)o.DefaultValue ? 1 : 0).Equals(1), out value);
+ }
+
+ public virtual bool TryPersist(OptionKey optionKey, object value)
+ {
+ return TryPersist(optionKey, value, (r, k, o, v) => r.SetValue(k, (bool)v ? 1 : 0, RegistryValueKind.DWord));
+ }
+
+ protected bool TryFetch(OptionKey optionKey, Func valueGetter, out object value)
{
if (this.RegistryKey == null)
{
@@ -40,21 +50,21 @@ public virtual bool TryFetch(OptionKey optionKey, out object value)
lock (Gate)
{
- using (var openSubKey = this.RegistryKey.OpenSubKey(collectionPathAndPropertyName.Item1))
+ using (var subKey = this.RegistryKey.OpenSubKey(collectionPathAndPropertyName.Item1))
{
- if (openSubKey == null)
+ if (subKey == null)
{
value = null;
return false;
}
- value = openSubKey.GetValue(collectionPathAndPropertyName.Item2, defaultValue: (bool)optionKey.Option.DefaultValue ? 1 : 0).Equals(1);
+ value = valueGetter(subKey, collectionPathAndPropertyName.Item2, optionKey.Option);
return true;
}
}
}
- public virtual bool TryPersist(OptionKey optionKey, object value)
+ protected bool TryPersist(OptionKey optionKey, object value, Action valueSetter)
{
// We ignore languageName, since the current use of this class is only for
// language-specific options that apply to a single language. The underlying option
@@ -74,10 +84,9 @@ public virtual bool TryPersist(OptionKey optionKey, object value)
{
using (var subKey = this.RegistryKey.CreateSubKey(collectionPathAndPropertyName.Item1))
{
- subKey.SetValue(collectionPathAndPropertyName.Item2, (bool)value ? 1 : 0, RegistryValueKind.DWord);
+ valueSetter(subKey, collectionPathAndPropertyName.Item2, optionKey.Option, value);
+ return true;
}
-
- return true;
}
}
}
diff --git a/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs b/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
index befde2ef1992fbd6b6059b996ce76af7e572209b..8124387957515863b47e849b46979f8e54c1d73d 100644
--- a/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
+++ b/src/VisualStudio/Core/Impl/Options/InternalOptionSerializer.cs
@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis.Editor.Shared.Options;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
+using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.VisualStudio.Shell;
using Microsoft.Win32;
using Roslyn.Utilities;
@@ -18,11 +19,10 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
PerformanceFunctionIdOptionsProvider.Name,
LoggerOptions.FeatureName,
CacheOptions.FeatureName,
- InternalDiagnosticsOptions.OptionName), Shared]
+ InternalDiagnosticsOptions.OptionName,
+ InternalSolutionCrawlerOptions.OptionName), Shared]
internal class InternalOptionSerializer : AbstractSettingStoreOptionSerializer
{
- private const string CachePath = @"Roslyn\Internal\Performance\Cache";
-
[ImportingConstructor]
public InternalOptionSerializer(SVsServiceProvider serviceProvider)
: base(serviceProvider)
@@ -51,28 +51,25 @@ public InternalOptionSerializer(SVsServiceProvider serviceProvider)
{
return Tuple.Create(@"Roslyn\Internal\Diagnostics", key.Name);
}
+ else if (key.Feature == InternalSolutionCrawlerOptions.OptionName)
+ {
+ return Tuple.Create(@"Roslyn\Internal\SolutionCrawler", key.Name);
+ }
+ else if (key.Feature == CacheOptions.FeatureName)
+ {
+ return Tuple.Create(@"Roslyn\Internal\Performance\Cache", key.Name);
+ }
throw ExceptionUtilities.Unreachable;
}
public override bool TryFetch(OptionKey optionKey, out object value)
{
- if (optionKey.Option.Feature == CacheOptions.FeatureName)
+ switch (optionKey.Option.Feature)
{
- lock (Gate)
- {
- using (var openSubKey = this.RegistryKey.OpenSubKey(CachePath))
- {
- if (openSubKey == null)
- {
- value = null;
- return false;
- }
-
- value = openSubKey.GetValue(optionKey.Option.Name, defaultValue: optionKey.Option.DefaultValue);
- return true;
- }
- }
+ case CacheOptions.FeatureName:
+ case InternalSolutionCrawlerOptions.OptionName:
+ return TryFetch(optionKey, (r, k, o) => r.GetValue(k, defaultValue: o.DefaultValue), out value);
}
return base.TryFetch(optionKey, out value);
@@ -80,16 +77,11 @@ public override bool TryFetch(OptionKey optionKey, out object value)
public override bool TryPersist(OptionKey optionKey, object value)
{
- if (optionKey.Option.Feature == CacheOptions.FeatureName)
+ switch (optionKey.Option.Feature)
{
- lock (Gate)
- {
- using (var subKey = this.RegistryKey.CreateSubKey(CachePath))
- {
- subKey.SetValue(optionKey.Option.Name, value, optionKey.Option.Type == typeof(int) ? RegistryValueKind.DWord : RegistryValueKind.QWord);
- return true;
- }
- }
+ case CacheOptions.FeatureName:
+ case InternalSolutionCrawlerOptions.OptionName:
+ return TryPersist(optionKey, value, (r, k, o, v) => r.SetValue(k, v, o.Type == typeof(int) ? RegistryValueKind.DWord : RegistryValueKind.QWord));
}
return base.TryPersist(optionKey, value);
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalOptionsControl.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalOptionsControl.cs
index 46973542bc3101dc65b051ce155a9a53b425b443..702c19691ee5f934c933e159c4e463417e0b952e 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalOptionsControl.cs
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalOptionsControl.cs
@@ -2,6 +2,7 @@
using System;
using System.Linq;
+using System.Windows;
using System.Windows.Controls;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Options;
@@ -19,9 +20,7 @@ public InternalOptionsControl(string featureOptionName, IServiceProvider service
{
if (!option.IsPerLanguage)
{
- var checkBox = new CheckBox() { Content = option.Name };
- BindToOption(checkBox, (Option)option);
- panel.Children.Add(checkBox);
+ AddOption(panel, option);
}
else
{
@@ -51,11 +50,79 @@ public InternalOptionsControl(string featureOptionName, IServiceProvider service
this.Content = viewer;
}
- private void AddPerLanguageOption(StackPanel panel, IOption option, string language)
+ private void AddOption(StackPanel panel, IOption option)
{
- var checkBox = new CheckBox() { Content = option.Name + " [" + language + "]" };
- BindToOption(checkBox, (PerLanguageOption)option, language);
- panel.Children.Add(checkBox);
+ var uiElement = CreateControl(option);
+ if (uiElement != null)
+ {
+ panel.Children.Add(uiElement);
+ }
+ }
+
+ private void AddPerLanguageOption(StackPanel panel, IOption option, string languageName)
+ {
+ var uiElement = CreateControl(option, languageName);
+ if (uiElement != null)
+ {
+ panel.Children.Add(uiElement);
+ }
+ }
+
+ private UIElement CreateControl(IOption option, string languageName = null)
+ {
+ if (option.Type == typeof(bool))
+ {
+ var checkBox = new CheckBox() { Content = option.Name + GetLanguage(languageName) };
+ BindToCheckBox(checkBox, option, languageName);
+ return checkBox;
+ }
+
+ if (option.Type == typeof(int))
+ {
+ var label = new Label() { Content = option.Name + GetLanguage(languageName) };
+ var textBox = new TextBox();
+ BindToTextBox(textBox, option, languageName);
+
+ var panel = new StackPanel();
+ panel.Children.Add(label);
+ panel.Children.Add(textBox);
+
+ return panel;
+ }
+
+ return null;
+ }
+
+ private string GetLanguage(string languageName)
+ {
+ if (languageName == null)
+ {
+ return string.Empty;
+ }
+
+ return " [" + languageName + "]";
+ }
+
+ private void BindToCheckBox(CheckBox checkBox, IOption option, string languageName = null)
+ {
+ if (languageName == null)
+ {
+ BindToOption(checkBox, (Option)option);
+ return;
+ }
+
+ BindToOption(checkBox, (PerLanguageOption)option, languageName);
+ }
+
+ private void BindToTextBox(TextBox textBox, IOption option, string languageName = null)
+ {
+ if (languageName == null)
+ {
+ BindToOption(textBox, (Option)option);
+ return;
+ }
+
+ BindToOption(textBox, (PerLanguageOption)option, languageName);
}
}
}
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalSolutionCrawlerPage.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalSolutionCrawlerPage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e47f2b400f52eacee1aaa2ae76f683aaf681e969
--- /dev/null
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/OptionPages/InternalSolutionCrawlerPage.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Runtime.InteropServices;
+using Microsoft.CodeAnalysis.SolutionCrawler;
+
+namespace Microsoft.VisualStudio.LanguageServices.Implementation.Options
+{
+ [Guid(Guids.RoslynOptionPageInternalSolutionCrawlerIdString)]
+ internal class InternalSolutionCrawlerPage : AbstractOptionPage
+ {
+ protected override AbstractOptionPageControl CreateOptionPage(IServiceProvider serviceProvider)
+ {
+ return new InternalOptionsControl(InternalSolutionCrawlerOptions.OptionName, serviceProvider);
+ }
+ }
+}
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
index 65146da7e3caefa1512def066ccf3ad682ad5837..5141c010e815fcb3977da42a6229d871cff74775 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindow.csproj
@@ -106,6 +106,7 @@
+
diff --git a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
index ea1be59696f98639c53e46f2d64385704e4e169f..8e538d946576ae4c9af3655cc697a8094cb3f36d 100644
--- a/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
+++ b/src/VisualStudio/VisualStudioDiagnosticsToolWindow/VisualStudioDiagnosticsWindowPackage.cs
@@ -34,6 +34,7 @@ namespace Roslyn.VisualStudio.DiagnosticsWindow
[ProvideOptionPage(typeof(PerformanceFunctionIdPage), @"Roslyn\Performance", @"FunctionId", categoryResourceID: 0, pageNameResourceID: 0, supportsAutomation: true, SupportsProfiles = false)]
[ProvideOptionPage(typeof(PerformanceLoggersPage), @"Roslyn\Performance", @"Loggers", categoryResourceID: 0, pageNameResourceID: 0, supportsAutomation: true, SupportsProfiles = false)]
[ProvideOptionPage(typeof(InternalDiagnosticsPage), @"Roslyn\Diagnostics", @"Internal", categoryResourceID: 0, pageNameResourceID: 0, supportsAutomation: true, SupportsProfiles = false)]
+ [ProvideOptionPage(typeof(InternalSolutionCrawlerPage), @"Roslyn\SolutionCrawler", @"Internal", categoryResourceID: 0, pageNameResourceID: 0, supportsAutomation: true, SupportsProfiles = false)]
// This attribute registers a tool window exposed by this package.
[ProvideToolWindow(typeof(DiagnosticsWindow))]
[Guid(GuidList.guidVisualStudioDiagnosticsWindowPkgString)]
diff --git a/src/Workspaces/Core/Portable/Log/FunctionIdOptions.cs b/src/Workspaces/Core/Portable/Log/FunctionIdOptions.cs
index d77bb0c1154a3336b539e36b030552b5e24fbaa9..5951b7a9751a8a48f1439667553cc3c354e58277 100644
--- a/src/Workspaces/Core/Portable/Log/FunctionIdOptions.cs
+++ b/src/Workspaces/Core/Portable/Log/FunctionIdOptions.cs
@@ -25,82 +25,11 @@ private static bool GetDefaultValue(FunctionId id)
{
switch (id)
{
- case FunctionId.TestEvent_NotUsed:
- return false;
-
- case FunctionId.Tagger_AdornmentManager_OnLayoutChanged:
- case FunctionId.Tagger_AdornmentManager_UpdateInvalidSpans:
- case FunctionId.Tagger_BatchChangeNotifier_NotifyEditorNow:
- case FunctionId.Tagger_BatchChangeNotifier_NotifyEditor:
- case FunctionId.Tagger_TagSource_ProcessNewTags:
- case FunctionId.Tagger_SyntacticClassification_TagComputer_GetTags:
- case FunctionId.Tagger_SemanticClassification_TagProducer_ProduceTags:
- case FunctionId.Tagger_BraceHighlighting_TagProducer_ProduceTags:
- case FunctionId.Tagger_LineSeparator_TagProducer_ProduceTags:
- case FunctionId.Tagger_Outlining_TagProducer_ProduceTags:
- case FunctionId.Tagger_Highlighter_TagProducer_ProduceTags:
- case FunctionId.Tagger_ReferenceHighlighting_TagProducer_ProduceTags:
- return false;
-
- case FunctionId.Tagger_Diagnostics_RecomputeTags:
- case FunctionId.Tagger_Diagnostics_Updated:
- return false;
-
- case FunctionId.Workspace_SourceText_GetChangeRanges:
- case FunctionId.Workspace_Recoverable_RecoverRootAsync:
- case FunctionId.Workspace_Recoverable_RecoverRoot:
- case FunctionId.Workspace_Recoverable_RecoverTextAsync:
- case FunctionId.Workspace_Recoverable_RecoverText:
- return false;
-
- case FunctionId.Misc_NonReentrantLock_BlockingWait:
- return false;
-
- case FunctionId.Cache_Created:
- case FunctionId.Cache_AddOrAccess:
- case FunctionId.Cache_Remove:
- case FunctionId.Cache_Evict:
- case FunctionId.Cache_EvictAll:
- case FunctionId.Cache_ItemRank:
- return false;
-
- case FunctionId.Simplifier_ReduceAsync:
- case FunctionId.Simplifier_ExpandNode:
- case FunctionId.Simplifier_ExpandToken:
- return false;
-
- case FunctionId.TemporaryStorageServiceFactory_ReadText:
- case FunctionId.TemporaryStorageServiceFactory_WriteText:
- case FunctionId.TemporaryStorageServiceFactory_ReadStream:
- case FunctionId.TemporaryStorageServiceFactory_WriteStream:
- return false;
-
- case FunctionId.WorkCoordinator_DocumentWorker_Enqueue:
- case FunctionId.WorkCoordinator_ProcessProjectAsync:
- case FunctionId.WorkCoordinator_ProcessDocumentAsync:
- case FunctionId.WorkCoordinator_SemanticChange_Enqueue:
- case FunctionId.WorkCoordinator_SemanticChange_EnqueueFromMember:
- case FunctionId.WorkCoordinator_SemanticChange_EnqueueFromType:
- case FunctionId.WorkCoordinator_SemanticChange_FullProjects:
- case FunctionId.WorkCoordinator_Project_Enqueue:
- case FunctionId.WorkCoordinator_ActivieFileEnqueue:
- return false;
-
- case FunctionId.Diagnostics_SyntaxDiagnostic:
- case FunctionId.Diagnostics_SemanticDiagnostic:
- case FunctionId.Diagnostics_ProjectDiagnostic:
- case FunctionId.Diagnostics_DocumentReset:
- case FunctionId.Diagnostics_DocumentOpen:
- case FunctionId.Diagnostics_RemoveDocument:
- case FunctionId.Diagnostics_RemoveProject:
- return false;
-
- case FunctionId.SuggestedActions_HasSuggestedActionsAsync:
- case FunctionId.SuggestedActions_GetSuggestedActions:
- return false;
-
+ // change not to enable any etw events by default.
+ // we used to couple this to other logger such as code marker but now it is only specific to etw.
+ // each events should be enabled specifically when needed.
default:
- return true;
+ return false;
}
}
}
diff --git a/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs b/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs
index 3a28656c19ba614556596c581e3248bad53e6230..de1048546f414b061cea641e33f7176012bc60c1 100644
--- a/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs
+++ b/src/Workspaces/Core/Portable/Log/KeyValueLogMessage.cs
@@ -59,7 +59,7 @@ protected override string CreateMessage()
return string.Join("|", _map.Select(kv => string.Format("{0}={1}", kv.Key, kv.Value)));
}
- public override void Free()
+ protected override void FreeCore()
{
if (_map != null)
{
diff --git a/src/Workspaces/Core/Portable/Log/LogMessage.cs b/src/Workspaces/Core/Portable/Log/LogMessage.cs
index 009d8065878501b646c64ecc6dcda50378547256..7db8feb369dcda53b8baf2c6c7c369f86a21018b 100644
--- a/src/Workspaces/Core/Portable/Log/LogMessage.cs
+++ b/src/Workspaces/Core/Portable/Log/LogMessage.cs
@@ -48,7 +48,7 @@ public static LogMessage Create(Func messageGetter, TArg arg
///
/// Logger will call this to return LogMessage to its pool
///
- public abstract void Free();
+ protected abstract void FreeCore();
public string GetMessage()
{
@@ -60,6 +60,13 @@ public string GetMessage()
return _message;
}
+ public void Free()
+ {
+ _message = null;
+
+ FreeCore();
+ }
+
private sealed class StaticLogMessage : LogMessage
{
private static readonly ObjectPool s_pool = SharedPools.Default();
@@ -77,7 +84,7 @@ protected override string CreateMessage()
return _message;
}
- public override void Free()
+ protected override void FreeCore()
{
if (_message == null)
{
@@ -108,7 +115,7 @@ protected override string CreateMessage()
return _messageGetter();
}
- public override void Free()
+ protected override void FreeCore()
{
if (_messageGetter == null)
{
@@ -141,7 +148,7 @@ protected override string CreateMessage()
return _messageGetter(_arg);
}
- public override void Free()
+ protected override void FreeCore()
{
if (_messageGetter == null)
{
@@ -177,7 +184,7 @@ protected override string CreateMessage()
return _messageGetter(_arg0, _arg1);
}
- public override void Free()
+ protected override void FreeCore()
{
if (_messageGetter == null)
{
@@ -216,7 +223,7 @@ protected override string CreateMessage()
return _messageGetter(_arg0, _arg1, _arg2);
}
- public override void Free()
+ protected override void FreeCore()
{
if (_messageGetter == null)
{
@@ -258,7 +265,7 @@ protected override string CreateMessage()
return _messageGetter(_arg0, _arg1, _arg2, _arg3);
}
- public override void Free()
+ protected override void FreeCore()
{
if (_messageGetter == null)
{