Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ public void AddAllTo(HashSet<Checksum> checksums)
}

[PerformanceSensitive("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1333566", AllowGenericEnumeration = false)]
internal static async Task FindAsync<TState>(
internal static async Task FindAsync<TState, TArg>(
AssetPath assetPath,
TextDocumentStates<TState> documentStates,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken) where TState : TextDocumentState
{
var hintDocument = assetPath.DocumentId;
Expand All @@ -68,7 +69,7 @@ internal static async Task FindAsync<TState>(
if (state != null)
{
Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksums));
await stateChecksums.FindAsync(assetPath, state, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await stateChecksums.FindAsync(assetPath, state, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
else
Expand All @@ -81,16 +82,17 @@ internal static async Task FindAsync<TState>(

Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksums));

await stateChecksums.FindAsync(assetPath, state, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await stateChecksums.FindAsync(assetPath, state, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
}

internal static void Find<T>(
internal static void Find<T, TArg>(
IReadOnlyList<T> values,
ChecksumCollection checksums,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken) where T : class
{
Contract.ThrowIfFalse(values.Count == checksums.Children.Length);
Expand All @@ -103,7 +105,7 @@ internal static void Find<T>(

var checksum = checksums.Children[i];
if (searchingChecksumsLeft.Remove(checksum))
onAssetFound(checksum, values[i]);
onAssetFound(checksum, values[i], arg);
}
}

Expand Down
68 changes: 36 additions & 32 deletions src/Workspaces/Core/Portable/Workspace/Solution/StateChecksums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,13 @@ public static SolutionCompilationStateChecksums Deserialize(ObjectReader reader)
return result;
}

public async Task FindAsync(
public async Task FindAsync<TArg>(
SolutionCompilationState compilationState,
ProjectCone? projectCone,
AssetPath assetPath,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -128,10 +129,10 @@ public async Task FindAsync(
if (assetPath.IncludeSolutionCompilationState)
{
if (assetPath.IncludeSolutionCompilationStateChecksums && searchingChecksumsLeft.Remove(this.Checksum))
onAssetFound(this.Checksum, this);
onAssetFound(this.Checksum, this, arg);

if (assetPath.IncludeSolutionSourceGeneratorExecutionVersionMap && searchingChecksumsLeft.Remove(this.SourceGeneratorExecutionVersionMap))
onAssetFound(this.SourceGeneratorExecutionVersionMap, compilationState.SourceGeneratorExecutionVersionMap);
onAssetFound(this.SourceGeneratorExecutionVersionMap, compilationState.SourceGeneratorExecutionVersionMap, arg);

if (compilationState.FrozenSourceGeneratedDocumentStates != null)
{
Expand All @@ -143,7 +144,7 @@ public async Task FindAsync(
{
await ChecksumCollection.FindAsync(
new AssetPath(AssetPathKind.DocumentText, assetPath.ProjectId, assetPath.DocumentId),
compilationState.FrozenSourceGeneratedDocumentStates, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
compilationState.FrozenSourceGeneratedDocumentStates, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}

// ... or one of the identities. In this case, we'll use the fact that there's a 1:1 correspondence between the
Expand All @@ -161,7 +162,7 @@ await ChecksumCollection.FindAsync(
if (searchingChecksumsLeft.Remove(identityChecksum))
{
Contract.ThrowIfFalse(compilationState.FrozenSourceGeneratedDocumentStates.TryGetState(documentId, out var state));
onAssetFound(identityChecksum, state.Identity);
onAssetFound(identityChecksum, state.Identity, arg);
}
}
}
Expand All @@ -175,7 +176,7 @@ await ChecksumCollection.FindAsync(
{
var id = FrozenSourceGeneratedDocuments.Value.Ids[i];
Contract.ThrowIfFalse(compilationState.FrozenSourceGeneratedDocumentStates.TryGetState(id, out var state));
onAssetFound(identityChecksum, state.Identity);
onAssetFound(identityChecksum, state.Identity, arg);
}
}
}
Expand All @@ -189,13 +190,13 @@ await ChecksumCollection.FindAsync(
// If we're not in a project cone, start the search at the top most state-checksum corresponding to the
// entire solution.
Contract.ThrowIfFalse(solutionState.TryGetStateChecksums(out var solutionChecksums));
await solutionChecksums.FindAsync(solutionState, projectCone, assetPath, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await solutionChecksums.FindAsync(solutionState, projectCone, assetPath, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
else
{
// Otherwise, grab the top-most state checksum for this cone and search within that.
Contract.ThrowIfFalse(solutionState.TryGetStateChecksums(projectCone.RootProjectId, out var solutionChecksums));
await solutionChecksums.FindAsync(solutionState, projectCone, assetPath, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await solutionChecksums.FindAsync(solutionState, projectCone, assetPath, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
}
Expand Down Expand Up @@ -264,12 +265,13 @@ public static SolutionStateChecksums Deserialize(ObjectReader reader)
return result;
}

public async Task FindAsync(
public async Task FindAsync<TArg>(
SolutionState solution,
ProjectCone? projectCone,
AssetPath assetPath,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -279,13 +281,13 @@ public async Task FindAsync(
if (assetPath.IncludeSolutionState)
{
if (assetPath.IncludeSolutionStateChecksums && searchingChecksumsLeft.Remove(Checksum))
onAssetFound(Checksum, this);
onAssetFound(Checksum, this, arg);

if (assetPath.IncludeSolutionAttributes && searchingChecksumsLeft.Remove(Attributes))
onAssetFound(Attributes, solution.SolutionAttributes);
onAssetFound(Attributes, solution.SolutionAttributes, arg);

if (assetPath.IncludeSolutionAnalyzerReferences)
ChecksumCollection.Find(solution.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, onAssetFound, cancellationToken);
ChecksumCollection.Find(solution.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, onAssetFound, arg, cancellationToken);
}

if (searchingChecksumsLeft.Count == 0)
Expand All @@ -304,7 +306,7 @@ public async Task FindAsync(
if (projectState != null &&
projectState.TryGetStateChecksums(out var projectStateChecksums))
{
await projectStateChecksums.FindAsync(projectState, assetPath, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await projectStateChecksums.FindAsync(projectState, assetPath, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
else
Expand All @@ -327,7 +329,7 @@ public async Task FindAsync(
if (!projectState.TryGetStateChecksums(out var projectStateChecksums))
continue;

await projectStateChecksums.FindAsync(projectState, assetPath, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await projectStateChecksums.FindAsync(projectState, assetPath, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
}
Expand Down Expand Up @@ -431,11 +433,12 @@ public static ProjectStateChecksums Deserialize(ObjectReader reader)
return result;
}

public async Task FindAsync(
public async Task FindAsync<TArg>(
ProjectState state,
AssetPath assetPath,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -449,38 +452,38 @@ public async Task FindAsync(
if (assetPath.IncludeProjects)
{
if (assetPath.IncludeProjectStateChecksums && searchingChecksumsLeft.Remove(Checksum))
onAssetFound(Checksum, this);
onAssetFound(Checksum, this, arg);

if (assetPath.IncludeProjectAttributes && searchingChecksumsLeft.Remove(Info))
onAssetFound(Info, state.ProjectInfo.Attributes);
onAssetFound(Info, state.ProjectInfo.Attributes, arg);

if (assetPath.IncludeProjectCompilationOptions && searchingChecksumsLeft.Remove(CompilationOptions))
{
var compilationOptions = state.CompilationOptions ?? throw new InvalidOperationException("We should not be trying to serialize a project with no compilation options; RemoteSupportedLanguages.IsSupported should have filtered it out.");
onAssetFound(CompilationOptions, compilationOptions);
onAssetFound(CompilationOptions, compilationOptions, arg);
}

if (assetPath.IncludeProjectParseOptions && searchingChecksumsLeft.Remove(ParseOptions))
{
var parseOptions = state.ParseOptions ?? throw new InvalidOperationException("We should not be trying to serialize a project with no parse options; RemoteSupportedLanguages.IsSupported should have filtered it out.");
onAssetFound(ParseOptions, parseOptions);
onAssetFound(ParseOptions, parseOptions, arg);
}

if (assetPath.IncludeProjectProjectReferences)
ChecksumCollection.Find(state.ProjectReferences, ProjectReferences, searchingChecksumsLeft, onAssetFound, cancellationToken);
ChecksumCollection.Find(state.ProjectReferences, ProjectReferences, searchingChecksumsLeft, onAssetFound, arg, cancellationToken);

if (assetPath.IncludeProjectMetadataReferences)
ChecksumCollection.Find(state.MetadataReferences, MetadataReferences, searchingChecksumsLeft, onAssetFound, cancellationToken);
ChecksumCollection.Find(state.MetadataReferences, MetadataReferences, searchingChecksumsLeft, onAssetFound, arg, cancellationToken);

if (assetPath.IncludeProjectAnalyzerReferences)
ChecksumCollection.Find(state.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, onAssetFound, cancellationToken);
ChecksumCollection.Find(state.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, onAssetFound, arg, cancellationToken);
}

if (assetPath.IncludeDocuments)
{
await ChecksumCollection.FindAsync(assetPath, state.DocumentStates, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await ChecksumCollection.FindAsync(assetPath, state.AdditionalDocumentStates, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await ChecksumCollection.FindAsync(assetPath, state.AnalyzerConfigDocumentStates, searchingChecksumsLeft, onAssetFound, cancellationToken).ConfigureAwait(false);
await ChecksumCollection.FindAsync(assetPath, state.DocumentStates, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
await ChecksumCollection.FindAsync(assetPath, state.AdditionalDocumentStates, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
await ChecksumCollection.FindAsync(assetPath, state.AnalyzerConfigDocumentStates, searchingChecksumsLeft, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}
}
Expand All @@ -502,24 +505,25 @@ public void AddAllTo(HashSet<Checksum> checksums)
checksums.AddIfNotNullChecksum(this.Text);
}

public async Task FindAsync(
public async Task FindAsync<TArg>(
AssetPath assetPath,
TextDocumentState state,
HashSet<Checksum> searchingChecksumsLeft,
Action<Checksum, object> onAssetFound,
Action<Checksum, object, TArg> onAssetFound,
TArg arg,
CancellationToken cancellationToken)
{
Debug.Assert(state.TryGetStateChecksums(out var stateChecksum) && this == stateChecksum);

cancellationToken.ThrowIfCancellationRequested();

if (assetPath.IncludeDocumentAttributes && searchingChecksumsLeft.Remove(Info))
onAssetFound(Info, state.Attributes);
onAssetFound(Info, state.Attributes, arg);

if (assetPath.IncludeDocumentText && searchingChecksumsLeft.Remove(Text))
{
var text = await SerializableSourceText.FromTextDocumentStateAsync(state, cancellationToken).ConfigureAwait(false);
onAssetFound(Text, text);
onAssetFound(Text, text, arg);
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions src/Workspaces/Remote/Core/SolutionAssetStorage.Scope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,16 @@ public async Task AddAssetsAsync(

await FindAssetsAsync(
assetPath, checksumsToFind,
(checksum, asset) => assetMap[checksum] = asset,
static (checksum, asset, assetMap) => assetMap[checksum] = asset,
assetMap,
cancellationToken).ConfigureAwait(false);

Contract.ThrowIfTrue(checksumsToFind.Count > 0);
Contract.ThrowIfTrue(assetMap.Count != numberOfChecksumsToSearch);
}

private async Task FindAssetsAsync(
AssetPath assetPath, HashSet<Checksum> remainingChecksumsToFind, Action<Checksum, object> onAssetFound, CancellationToken cancellationToken)
private async Task FindAssetsAsync<TArg>(
AssetPath assetPath, HashSet<Checksum> remainingChecksumsToFind, Action<Checksum, object, TArg> onAssetFound, TArg arg, CancellationToken cancellationToken)
{
var solutionState = this.CompilationState;

Expand All @@ -77,13 +78,13 @@ private async Task FindAssetsAsync(
// If we're not in a project cone, start the search at the top most state-checksum corresponding to the
// entire solution.
Contract.ThrowIfFalse(solutionState.TryGetStateChecksums(out var stateChecksums));
await stateChecksums.FindAsync(solutionState, this.ProjectCone, assetPath, remainingChecksumsToFind, onAssetFound, cancellationToken).ConfigureAwait(false);
await stateChecksums.FindAsync(solutionState, this.ProjectCone, assetPath, remainingChecksumsToFind, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
else
{
// Otherwise, grab the top-most state checksum for this cone and search within that.
Contract.ThrowIfFalse(solutionState.TryGetStateChecksums(this.ProjectCone.RootProjectId, out var stateChecksums));
await stateChecksums.FindAsync(solutionState, this.ProjectCone, assetPath, remainingChecksumsToFind, onAssetFound, cancellationToken).ConfigureAwait(false);
await stateChecksums.FindAsync(solutionState, this.ProjectCone, assetPath, remainingChecksumsToFind, onAssetFound, arg, cancellationToken).ConfigureAwait(false);
}
}

Expand Down
Loading