Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into syncLess
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Apr 8, 2024
2 parents c46b013 + 420d830 commit 3ed60b3
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,17 @@
namespace Microsoft.CodeAnalysis.Diagnostics;

[ExportWorkspaceServiceFactory(typeof(IBuildOnlyDiagnosticsService), ServiceLayer.Default), Shared]
internal sealed class BuildOnlyDiagnosticsServiceFactory : IWorkspaceServiceFactory
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class BuildOnlyDiagnosticsServiceFactory() : IWorkspaceServiceFactory
{
[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public BuildOnlyDiagnosticsServiceFactory()
{
}

public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
=> new BuildOnlyDiagnosticsService(workspaceServices.Workspace);

private sealed class BuildOnlyDiagnosticsService : IBuildOnlyDiagnosticsService
{
private readonly object _gate = new();
private readonly Dictionary<DocumentId, ImmutableArray<DiagnosticData>> _documentDiagnostics = [];
private readonly Dictionary<ProjectId, ImmutableArray<DiagnosticData>> _projectDiagnostics = [];

public BuildOnlyDiagnosticsService(Workspace workspace)
{
Expand Down Expand Up @@ -61,18 +56,12 @@ private void OnWorkspaceChanged(object? sender, WorkspaceChangeEventArgs e)
}
}

public void AddBuildOnlyDiagnostics(Solution solution, ProjectId? projectId, DocumentId? documentId, ImmutableArray<DiagnosticData> diagnostics)
public void AddBuildOnlyDiagnostics(DocumentId documentId, ImmutableArray<DiagnosticData> diagnostics)
{
lock (_gate)
{
if (documentId != null)
{
_documentDiagnostics[documentId] = diagnostics;
}
else if (projectId != null)
{
_projectDiagnostics[projectId] = diagnostics;
}
}
}

Expand All @@ -81,7 +70,6 @@ private void ClearAllDiagnostics()
lock (_gate)
{
_documentDiagnostics.Clear();
_projectDiagnostics.Clear();
}
}

Expand All @@ -103,43 +91,24 @@ private void ClearDiagnostics(Project? project)

lock (_gate)
{
_projectDiagnostics.Remove(project.Id);
foreach (var documentId in project.DocumentIds)
_documentDiagnostics.Remove(documentId);
}
}

public void ClearBuildOnlyDiagnostics(Solution solution, ProjectId? projectId, DocumentId? documentId)
public void ClearBuildOnlyDiagnostics(Project project, DocumentId? documentId)
{
if (documentId != null)
ClearDiagnostics(documentId);
else
ClearDiagnostics(solution.GetProject(projectId));
ClearDiagnostics(project);
}

public ImmutableArray<DiagnosticData> GetBuildOnlyDiagnostics(DocumentId documentId)
{
lock (_gate)
{
if (_documentDiagnostics.TryGetValue(documentId, out var diagnostics))
{
return diagnostics;
}

return [];
}
}

public ImmutableArray<DiagnosticData> GetBuildOnlyDiagnostics(ProjectId projectId)
{
lock (_gate)
{
if (_projectDiagnostics.TryGetValue(projectId, out var diagnostics))
{
return diagnostics;
}

return [];
return _documentDiagnostics.TryGetValue(documentId, out var diagnostics) ? diagnostics : [];
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@ namespace Microsoft.CodeAnalysis.Diagnostics;
/// </summary>
internal interface IBuildOnlyDiagnosticsService : IWorkspaceService
{
void AddBuildOnlyDiagnostics(Solution solution, ProjectId? projectId, DocumentId? documentId, ImmutableArray<DiagnosticData> diagnostics);
void AddBuildOnlyDiagnostics(DocumentId documentId, ImmutableArray<DiagnosticData> diagnostics);

void ClearBuildOnlyDiagnostics(Solution solution, ProjectId? projectId, DocumentId? documentId);
void ClearBuildOnlyDiagnostics(Project project, DocumentId? documentId);

ImmutableArray<DiagnosticData> GetBuildOnlyDiagnostics(DocumentId documentId);

ImmutableArray<DiagnosticData> GetBuildOnlyDiagnostics(ProjectId projectId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@
using Microsoft.CodeAnalysis.SolutionCrawler;
using Roslyn.Utilities;

#pragma warning disable CA1200 // Avoid using cref tags with a prefix

namespace Microsoft.VisualStudio.LanguageServices.Implementation.TaskList;

using ProjectErrorMap = ImmutableDictionary<ProjectId, ImmutableArray<DiagnosticData>>;

/// <summary>
/// Diagnostic source for warnings and errors reported from explicit build command invocations in Visual Studio.
/// VS workspaces calls into us when a build is invoked or completed in Visual Studio.
Expand Down Expand Up @@ -520,13 +516,16 @@ private void ProcessAndRaiseDiagnosticsUpdated(ImmutableArray<DiagnosticsUpdated
{
if (args.Kind == DiagnosticsUpdatedKind.DiagnosticsCreated)
{
RoslynDebug.AssertNotNull(args.Solution);
_buildOnlyDiagnosticsService.AddBuildOnlyDiagnostics(args.Solution, args.ProjectId, args.DocumentId, args.Diagnostics);
Contract.ThrowIfNull(args.Solution);
if (args.DocumentId != null)
_buildOnlyDiagnosticsService.AddBuildOnlyDiagnostics(args.DocumentId, args.Diagnostics);
}
else if (args.Kind == DiagnosticsUpdatedKind.DiagnosticsRemoved)
{
RoslynDebug.AssertNotNull(args.Solution);
_buildOnlyDiagnosticsService.ClearBuildOnlyDiagnostics(args.Solution, args.ProjectId, args.DocumentId);
Contract.ThrowIfNull(args.Solution);
var project = args.Solution.GetProject(args.ProjectId);
if (project != null)
_buildOnlyDiagnosticsService.ClearBuildOnlyDiagnostics(project, args.DocumentId);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.Diagnostics

Dim buildOnlyDiagnosticService = workspace.Services.GetRequiredService(Of IBuildOnlyDiagnosticsService)
Assert.Empty(buildOnlyDiagnosticService.GetBuildOnlyDiagnostics(project.DocumentIds.First()))
Assert.Empty(buildOnlyDiagnosticService.GetBuildOnlyDiagnostics(project.Id))

Dim diagnostics = source.GetBuildErrors()
Assert.Equal(2, diagnostics.Length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
Expand All @@ -23,8 +24,11 @@ internal sealed partial class RecoverableTextAndVersion
private sealed partial class RecoverableText
{
// enforce saving in a queue so save's don't overload the thread pool.
private static Task s_latestTask = Task.CompletedTask;
private static readonly NonReentrantLock s_taskGuard = new();
private static readonly AsyncBatchingWorkQueue<(RecoverableText recoverableText, SourceText sourceText)> s_saveQueue =
new(TimeSpan.Zero,
SaveAllAsync,
AsynchronousOperationListenerProvider.NullListener,
CancellationToken.None);

/// <summary>
/// Lazily created. Access via the <see cref="Gate"/> property.
Expand Down Expand Up @@ -136,27 +140,16 @@ private void UpdateWeakReferenceAndEnqueueSaveTask_NoLock(SourceText instance)
if (!_saved)
{
_saved = true;
using (s_taskGuard.DisposableWait())
{
// force all save tasks to be in sequence so we don't hog all the threads.
s_latestTask = s_latestTask.SafeContinueWithFromAsync(async _ =>
{
// Now defer to our subclass to actually save the instance to secondary storage.
await SaveAsync(instance, CancellationToken.None).ConfigureAwait(false);
// Only set _initialValue to null if the saveTask completed successfully. If the save did not complete,
// we want to keep it around to service future requests. Once we do clear out this value, then all
// future request will either retrieve the value from the weak reference (if anyone else is holding onto
// it), or will recover from underlying storage.
_initialValue = null;
},
CancellationToken.None,
// Ensure we run continuations asynchronously so that we don't start running the continuation while
// holding s_taskGuard.
TaskContinuationOptions.RunContinuationsAsynchronously,
TaskScheduler.Default);
}

s_saveQueue.AddWork((this, instance));
}
}

private static async ValueTask SaveAllAsync(
ImmutableSegmentedList<(RecoverableText recoverableText, SourceText sourceText)> list, CancellationToken cancellationToken)
{
foreach (var (recoverableText, sourceText) in list)
await recoverableText.SaveAsync(sourceText, cancellationToken).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ namespace Microsoft.CodeAnalysis;
/// </summary>
internal sealed partial class RecoverableTextAndVersion(ITextAndVersionSource initialSource, SolutionServices services) : ITextAndVersionSource
{

// Starts as ITextAndVersionSource and is replaced with RecoverableText when the TextAndVersion value is requested.
// At that point the initial source is no longer referenced and can be garbage collected.
private object _initialSourceOrRecoverableText = initialSource;
Expand Down Expand Up @@ -192,6 +191,12 @@ private async Task SaveAsync(SourceText text, CancellationToken cancellationToke

// make sure write is done before setting _storage field
Interlocked.CompareExchange(ref _storage, storage, null);

// Only set _initialValue to null once writing to the storage service completes fully. If the save did not
// complete, we want to keep it around to service future requests. Once we do clear out this value, then
// all future request will either retrieve the value from the weak reference (if anyone else is holding onto
// it), or will recover from underlying storage.
_initialValue = null;
}

public bool TryGetTextVersion(LoadTextOptions options, out VersionStamp version)
Expand Down
7 changes: 4 additions & 3 deletions src/Workspaces/Remote/Core/RemoteHostAssetSerialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Diagnostics;
using System.IO;
using System.IO.Pipelines;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.PooledObjects;
Expand Down Expand Up @@ -88,7 +89,7 @@ static async ValueTask<ImmutableArray<T>> ReadDataSuppressedFlowAsync(

public static ImmutableArray<T> ReadData<T>(Stream stream, Checksum solutionChecksum, int objectCount, ISerializerService serializerService, CancellationToken cancellationToken)
{
using var _ = ArrayBuilder<T>.GetInstance(objectCount, out var results);
var results = new T[objectCount];

using var reader = ObjectReader.GetReader(stream, leaveOpen: true, cancellationToken);

Expand All @@ -104,10 +105,10 @@ public static ImmutableArray<T> ReadData<T>(Stream stream, Checksum solutionChec
// in service hub, cancellation means simply closed stream
var result = serializerService.Deserialize(kind, reader, cancellationToken);
Contract.ThrowIfNull(result);
results.Add((T)result);
results[i] = (T)result;
}

return results.ToImmutableAndClear();
return ImmutableCollectionsMarshal.AsImmutableArray(results);
}
}
}

0 comments on commit 3ed60b3

Please sign in to comment.