Skip to content

Commit 11d5cc0

Browse files
author
Adam Ratzman
committed
Fix analyzer failures
1 parent a6ddf4b commit 11d5cc0

File tree

10 files changed

+83
-51
lines changed

10 files changed

+83
-51
lines changed

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/HotReload/ProjectHotReloadSessionManager.cs

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ internal class ProjectHotReloadSessionManager : OnceInitializedOnceDisposedAsync
2323
// Protect the state from concurrent access. For example, our Process.Exited event
2424
// handler may run on one thread while we're still setting up the session on
2525
// another. To ensure consistent and proper behavior we need to serialize access.
26-
private readonly AsyncSemaphore _semaphore = new(initialCount: 1);
26+
private readonly ReentrantSemaphore _semaphore;
2727

2828
private readonly Dictionary<int, HotReloadState> _activeSessions = new();
2929
private HotReloadState? _pendingSessionState = null;
3030
private int _nextUniqueId = 1;
31+
private CancellationToken _cancellationToken;
3132

3233
public bool HasActiveHotReloadSessions => _activeSessions.Count != 0;
3334

@@ -39,7 +40,8 @@ public ProjectHotReloadSessionManager(
3940
IActiveDebugFrameworkServices activeDebugFrameworkServices,
4041
Lazy<IProjectHotReloadAgent> projectHotReloadAgent,
4142
Lazy<IHotReloadDiagnosticOutputService> hotReloadDiagnosticOutputService,
42-
Lazy<IProjectHotReloadNotificationService> projectHotReloadNotificationService)
43+
Lazy<IProjectHotReloadNotificationService> projectHotReloadNotificationService,
44+
JoinableTaskContext joinableTaskContext)
4345
: base(threadingService.JoinableTaskContext)
4446
{
4547
_project = project;
@@ -48,12 +50,16 @@ public ProjectHotReloadSessionManager(
4850
_projectHotReloadAgent = projectHotReloadAgent;
4951
_hotReloadDiagnosticOutputService = hotReloadDiagnosticOutputService;
5052
_projectHotReloadNotificationService = projectHotReloadNotificationService;
53+
_semaphore = ReentrantSemaphore.Create(initialCount: 1, joinableTaskContext: joinableTaskContext, mode: ReentrantSemaphore.ReentrancyMode.NotRecognized);
5154
}
5255

53-
public async Task ActivateSessionAsync(int processId, bool runningUnderDebugger, string projectName)
56+
public Task ActivateSessionAsync(int processId, bool runningUnderDebugger, string projectName)
57+
{
58+
return _semaphore.ExecuteAsync(() => ActivateSessionInternalAsync(processId, runningUnderDebugger, projectName), _cancellationToken);
59+
}
60+
61+
private async Task ActivateSessionInternalAsync(int processId, bool runningUnderDebugger, string projectName)
5462
{
55-
using AsyncSemaphore.Releaser semaphoreReleaser = await _semaphore.EnterAsync();
56-
5763
if (_pendingSessionState is not null)
5864
{
5965
Assumes.NotNull(_pendingSessionState.Session);
@@ -138,10 +144,13 @@ public async Task ActivateSessionAsync(int processId, bool runningUnderDebugger,
138144
}
139145
}
140146

141-
public async Task<bool> TryCreatePendingSessionAsync(IDictionary<string, string> environmentVariables)
147+
public Task<bool> TryCreatePendingSessionAsync(IDictionary<string, string> environmentVariables)
148+
{
149+
return _semaphore.ExecuteAsync(() => TryCreatePendingSessionInternalAsync(environmentVariables), _cancellationToken).AsTask();
150+
}
151+
152+
public async ValueTask<bool> TryCreatePendingSessionInternalAsync(IDictionary<string, string> environmentVariables)
142153
{
143-
using AsyncSemaphore.Releaser semaphoreReleaser = await _semaphore.EnterAsync();
144-
145154
if (await DebugFrameworkSupportsHotReloadAsync()
146155
&& await GetDebugFrameworkVersionAsync() is string frameworkVersion
147156
&& !string.IsNullOrWhiteSpace(frameworkVersion))
@@ -185,13 +194,17 @@ public async Task<bool> TryCreatePendingSessionAsync(IDictionary<string, string>
185194

186195
protected override Task InitializeCoreAsync(CancellationToken cancellationToken)
187196
{
197+
_cancellationToken = cancellationToken;
188198
return Task.CompletedTask;
189199
}
190200

191-
protected override async Task DisposeCoreAsync(bool initialized)
201+
protected override Task DisposeCoreAsync(bool initialized)
202+
{
203+
return _semaphore.ExecuteAsync(DisposeCoreInternalAsync, _cancellationToken);
204+
}
205+
206+
private Task DisposeCoreInternalAsync()
192207
{
193-
using AsyncSemaphore.Releaser semaphoreRelease = await _semaphore.EnterAsync();
194-
195208
foreach (HotReloadState sessionState in _activeSessions.Values)
196209
{
197210
Assumes.NotNull(sessionState.Process);
@@ -202,6 +215,8 @@ protected override async Task DisposeCoreAsync(bool initialized)
202215
}
203216

204217
_activeSessions.Clear();
218+
219+
return Task.CompletedTask;
205220
}
206221

207222
private void WriteOutputMessage(HotReloadLogMessage hotReloadLogMessage, CancellationToken cancellationToken) => _hotReloadDiagnosticOutputService.Value.WriteLine(hotReloadLogMessage, cancellationToken);
@@ -326,7 +341,7 @@ private async Task OnProcessExitedAsync(HotReloadState hotReloadState)
326341
),
327342
default);
328343

329-
await StopProjectAsync(hotReloadState, default);
344+
await _semaphore.ExecuteAsync(() => StopProjectAsync(hotReloadState, default), _cancellationToken);
330345

331346
hotReloadState.Process.Exited -= hotReloadState.OnProcessExited;
332347
}
@@ -347,13 +362,11 @@ private static Task OnAfterChangesAppliedAsync(HotReloadState hotReloadState, Ca
347362
return Task.CompletedTask;
348363
}
349364

350-
private async Task<bool> StopProjectAsync(HotReloadState hotReloadState, CancellationToken cancellationToken)
365+
private async ValueTask<bool> StopProjectAsync(HotReloadState hotReloadState, CancellationToken cancellationToken)
351366
{
352367
Assumes.NotNull(hotReloadState.Session);
353368
Assumes.NotNull(hotReloadState.Process);
354369

355-
using AsyncSemaphore.Releaser semaphoreReleaser = await _semaphore.EnterAsync();
356-
357370
int sessionCountOnEntry = _activeSessions.Count;
358371

359372
try
@@ -398,10 +411,13 @@ private async Task<bool> StopProjectAsync(HotReloadState hotReloadState, Cancell
398411
}
399412

400413
/// <inheritdoc />
401-
public async Task ApplyHotReloadUpdateAsync(Func<IDeltaApplier, CancellationToken, Task> applyFunction, CancellationToken cancelToken)
414+
public Task ApplyHotReloadUpdateAsync(Func<IDeltaApplier, CancellationToken, Task> applyFunction, CancellationToken cancelToken)
415+
{
416+
return _semaphore.ExecuteAsync(() => ApplyHotReloadUpdateInternalAsync(applyFunction, cancelToken), cancelToken);
417+
}
418+
419+
private async Task ApplyHotReloadUpdateInternalAsync(Func<IDeltaApplier, CancellationToken, Task> applyFunction, CancellationToken cancelToken)
402420
{
403-
using AsyncSemaphore.Releaser semaphoreRelease = await _semaphore.EnterAsync(cancelToken);
404-
405421
// Run the updates in parallel
406422
List<Task> updateTasks = new List<Task>();
407423
foreach (HotReloadState sessionState in _activeSessions.Values)
@@ -451,7 +467,7 @@ public Task OnAfterChangesAppliedAsync(CancellationToken cancellationToken)
451467

452468
public Task<bool> StopProjectAsync(CancellationToken cancellationToken)
453469
{
454-
return _sessionManager.StopProjectAsync(this, cancellationToken);
470+
return _sessionManager._semaphore.ExecuteAsync(() => _sessionManager.StopProjectAsync(this, cancellationToken), _sessionManager._cancellationToken).AsTask();
455471
}
456472

457473
public Task<bool> RestartProjectAsync(CancellationToken cancellationToken)

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/LanguageServices/LanguageServiceHost.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ protected override async Task InitializeCoreAsync(CancellationToken cancellation
137137

138138
ITargetBlock<IProjectVersionedValue<(ConfiguredProject ActiveConfiguredProject, ConfigurationSubscriptionSources Sources)>> actionBlock
139139
= DataflowBlockFactory.CreateActionBlock<IProjectVersionedValue<(ConfiguredProject ActiveConfiguredProject, ConfigurationSubscriptionSources Sources)>>(
140-
update => OnSlicesChanged(update, cancellationToken),
140+
update => OnSlicesChangedAsync(update, cancellationToken),
141141
_unconfiguredProject,
142142
ProjectFaultSeverity.LimitedFunctionality,
143143
nameFormat: "LanguageServiceHostSlices {1}");
@@ -190,7 +190,7 @@ protected override async Task InitializeCoreAsync(CancellationToken cancellation
190190

191191
return;
192192

193-
async Task OnSlicesChanged(IProjectVersionedValue<(ConfiguredProject ActiveConfiguredProject, ConfigurationSubscriptionSources Sources)> update, CancellationToken cancellationToken)
193+
async Task OnSlicesChangedAsync(IProjectVersionedValue<(ConfiguredProject ActiveConfiguredProject, ConfigurationSubscriptionSources Sources)> update, CancellationToken cancellationToken)
194194
{
195195
ProjectConfiguration activeProjectConfiguration = update.Value.ActiveConfiguredProject.ProjectConfiguration;
196196
ConfigurationSubscriptionSources sources = update.Value.Sources;

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/LaunchProfiles/LaunchProfileActionBase.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ public async Task OnRequestProcessFinishedAsync(IQueryProcessRequest request)
130130
UIPropertyDataProducer.CreateUIPropertyValues(request.QueryExecutionContext, launchProfileEntity, state.ProjectState, state.PropertiesContext, state.Rule, s_requestedPropertyProperties));
131131
launchProfileEntity.SetRelatedEntities(LaunchProfileType.PropertiesPropertyName, properties);
132132

133-
await PopulateEditorsAndValues(properties);
133+
await PopulateEditorsAndValuesAsync(properties);
134134
}
135135

136136
returnedLaunchProfiles.Add(launchProfileEntity);
@@ -165,7 +165,7 @@ public async Task OnRequestProcessFinishedAsync(IQueryProcessRequest request)
165165

166166
await ResultReceiver.OnRequestProcessFinishedAsync(request);
167167

168-
static async Task PopulateSupportedValuesAndConfigurations(ImmutableArray<IEntityValue> valueEntities)
168+
static async Task PopulateSupportedValuesAndConfigurationsAsync(ImmutableArray<IEntityValue> valueEntities)
169169
{
170170
foreach (IEntityValue valueEntity in valueEntities)
171171
{
@@ -197,7 +197,7 @@ static void PopulateEditorMetadata(ImmutableArray<IEntityValue> editors)
197197
}
198198
}
199199

200-
async Task PopulateEditorsAndValues(ImmutableArray<IEntityValue> properties)
200+
async Task PopulateEditorsAndValuesAsync(ImmutableArray<IEntityValue> properties)
201201
{
202202
foreach (IEntityValue propertyEntity in properties)
203203
{
@@ -215,7 +215,7 @@ async Task PopulateEditorsAndValues(ImmutableArray<IEntityValue> properties)
215215
await UIPropertyValueDataProducer.CreateUIPropertyValueValuesAsync(request.QueryExecutionContext, propertyEntity, propertyProviderState.ProjectState, propertyProviderState.ContainingRule, propertyProviderState.PropertiesContext, propertyProviderState.PropertyName, s_requestedValueProperties));
216216
propertyEntity.SetRelatedEntities(UIPropertyType.ValuesPropertyName, values);
217217

218-
await PopulateSupportedValuesAndConfigurations(values);
218+
await PopulateSupportedValuesAndConfigurationsAsync(values);
219219
}
220220
}
221221
}

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/Query/PropertyPages/PropertyPageDataProducer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ public static async Task<IEnumerable<IEntityValue>> CreatePropertyPageValuesAsyn
104104
{
105105
if (await project.GetProjectLevelPropertyPagesCatalogAsync() is IPropertyPagesCatalog projectCatalog)
106106
{
107-
return createPropertyPageValuesAsync();
107+
return createPropertyPageValues();
108108
}
109109

110110
return Enumerable.Empty<IEntityValue>();
111111

112-
IEnumerable<IEntityValue> createPropertyPageValuesAsync()
112+
IEnumerable<IEntityValue> createPropertyPageValues()
113113
{
114114
IProjectState projectState = new PropertyPageProjectState(project);
115115
QueryProjectPropertiesContext propertiesContext = new QueryProjectPropertiesContext(isProjectFile: true, project.FullPath, itemType: null, itemName: null);

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.Subscription.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private sealed class Subscription : ISubscription
4242
/// <summary>
4343
/// Prevent overlapping requests.
4444
/// </summary>
45-
private readonly AsyncSemaphore _semaphore = new(1);
45+
private readonly ReentrantSemaphore _semaphore;
4646

4747
private int _disposed;
4848

@@ -58,8 +58,10 @@ private sealed class Subscription : ISubscription
5858
/// </summary>
5959
private readonly CancellationTokenSource _disposeTokenSource = new();
6060

61-
public Subscription(IUpToDateCheckConfiguredInputDataSource inputDataSource, ConfiguredProject configuredProject, IUpToDateCheckHost host, IUpToDateCheckStatePersistence persistence)
61+
public Subscription(IUpToDateCheckConfiguredInputDataSource inputDataSource, ConfiguredProject configuredProject, IUpToDateCheckHost host, IUpToDateCheckStatePersistence persistence, JoinableTaskContext joinableTaskContext)
6262
{
63+
_semaphore = ReentrantSemaphore.Create(initialCount: 1, joinableTaskContext: joinableTaskContext, mode: ReentrantSemaphore.ReentrancyMode.NotRecognized);
64+
6365
Requires.NotNull(inputDataSource);
6466
Requires.NotNull(configuredProject);
6567

@@ -96,23 +98,24 @@ public async Task<bool> RunAsync(
9698
}
9799

98100
// Prevent overlapping requests
99-
using AsyncSemaphore.Releaser _ = await _semaphore.EnterAsync(token);
100-
101-
token.ThrowIfCancellationRequested();
101+
return await _semaphore.ExecuteAsync(async () =>
102+
{
103+
token.ThrowIfCancellationRequested();
102104

103-
IProjectVersionedValue<UpToDateCheckConfiguredInput> state;
105+
IProjectVersionedValue<UpToDateCheckConfiguredInput> state;
104106

105-
using (_inputDataSource.Join())
106-
{
107-
// Wait for our state to be up to date with that of the project
108-
state = await _inputDataSource.SourceBlock.GetLatestVersionAsync(
109-
_configuredProject,
110-
cancellationToken: token);
111-
}
107+
using (_inputDataSource.Join())
108+
{
109+
// Wait for our state to be up to date with that of the project
110+
state = await _inputDataSource.SourceBlock.GetLatestVersionAsync(
111+
_configuredProject,
112+
cancellationToken: token);
113+
}
112114

113-
(bool upToDate, _lastCheckedConfigurations) = await func(state.Value, _persistence, token);
115+
(bool upToDate, _lastCheckedConfigurations) = await func(state.Value, _persistence, token);
114116

115-
return upToDate;
117+
return upToDate;
118+
}, cancellationToken);
116119
}
117120

118121
public async Task UpdateLastSuccessfulBuildStartTimeUtcAsync(DateTime lastSuccessfulBuildStartTimeUtc, bool isRebuild)

src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/ProjectSystem/VS/UpToDate/BuildUpToDateCheck.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ internal sealed partial class BuildUpToDateCheck
4949
private readonly ISafeProjectGuidService _guidService;
5050
private readonly IUpToDateCheckHost _upToDateCheckHost;
5151
private readonly ICopyItemAggregator _copyItemAggregator;
52+
private readonly JoinableTaskContext _joinableTaskContext;
5253

5354
private IImmutableDictionary<string, string> _lastGlobalProperties = ImmutableStringDictionary<string>.EmptyOrdinal;
5455
private string? _lastFailureReason;
@@ -85,7 +86,8 @@ public BuildUpToDateCheck(
8586
IFileSystem fileSystem,
8687
ISafeProjectGuidService guidService,
8788
IUpToDateCheckHost upToDateCheckHost,
88-
ICopyItemAggregator copyItemAggregator)
89+
ICopyItemAggregator copyItemAggregator,
90+
JoinableTaskContext joinableTaskContext)
8991
{
9092
_solutionBuildContextProvider = solutionBuildContextProvider;
9193
_solutionBuildEventListener = solutionBuildEventListener;
@@ -99,10 +101,11 @@ public BuildUpToDateCheck(
99101
_guidService = guidService;
100102
_upToDateCheckHost = upToDateCheckHost;
101103
_copyItemAggregator = copyItemAggregator;
104+
_joinableTaskContext = joinableTaskContext;
102105

103106
UpToDateCheckers = new OrderPrecedenceImportCollection<IBuildUpToDateCheckProvider>(projectCapabilityCheckProvider: configuredProject);
104107

105-
_subscription = new Subscription(inputDataSource, configuredProject, upToDateCheckHost, persistence);
108+
_subscription = new Subscription(inputDataSource, configuredProject, upToDateCheckHost, persistence, joinableTaskContext);
106109
}
107110

108111
public Task ActivateAsync()
@@ -131,7 +134,7 @@ public void Dispose()
131134

132135
private void RecycleSubscription()
133136
{
134-
ISubscription subscription = Interlocked.Exchange(ref _subscription, new Subscription(_inputDataSource, _configuredProject, _upToDateCheckHost, _persistence));
137+
ISubscription subscription = Interlocked.Exchange(ref _subscription, new Subscription(_inputDataSource, _configuredProject, _upToDateCheckHost, _persistence, _joinableTaskContext));
135138

136139
subscription.Dispose();
137140
}

src/Microsoft.VisualStudio.ProjectSystem.Managed/ProjectSystem/Debug/LaunchProfile.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ internal static async Task<LaunchProfile> ReplaceTokensAsync(ILaunchProfile prof
7777
{
7878
return profile switch
7979
{
80-
ILaunchProfile2 profile2 => ReplaceValuesAsync(profile2.OtherSettings, ReplaceIfString),
81-
_ => ReplaceValuesAsync(profile.FlattenOtherSettings(), ReplaceIfString)
80+
ILaunchProfile2 profile2 => ReplaceValuesAsync(profile2.OtherSettings, ReplaceIfStringAsync),
81+
_ => ReplaceValuesAsync(profile.FlattenOtherSettings(), ReplaceIfStringAsync)
8282
};
8383

84-
async Task<object> ReplaceIfString(object o)
84+
async Task<object> ReplaceIfStringAsync(object o)
8585
{
8686
return o switch
8787
{
@@ -94,7 +94,7 @@ async Task<object> ReplaceIfString(object o)
9494
static async Task<ImmutableArray<(string Key, T Value)>> ReplaceValuesAsync<T>(ImmutableArray<(string Key, T Value)> source, Func<T, Task<T>> replaceAsync)
9595
where T : class
9696
{
97-
// We will only allocate a new array if a substituion is made
97+
// We will only allocate a new array if a substitution is made
9898
ImmutableArray<(string, T)>.Builder? builder = null;
9999

100100
for (int index = 0; index < source.Length; index++)

tests/Common/ThrowingTraceListener.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information.
22

33
using System.Diagnostics;
4+
#if !NET8_0_OR_GREATER
45
using System.Runtime.Serialization;
6+
#endif
57

68
namespace Microsoft.VisualStudio.Diagnostics
79
{

0 commit comments

Comments
 (0)