/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Workspaces/Remote/Core/AbstractAssetProvider.cs
186 строк
11 KB
Cyrus Najmabadi
Remove unnecessary imports
10 мар 2025, 17:04
10 мар 2025, 17:04
58c992f
Код
Авторство
О чём код?
// 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 file in the project root for more information. using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Serialization; namespace Microsoft.CodeAnalysis.Remote; /// <summary> /// Provides corresponding data of the given checksum /// </summary> internal abstract class AbstractAssetProvider { /// <summary> /// return data of type T whose checksum is the given checksum /// </summary> public abstract ValueTask<T> GetAssetAsync<T>(AssetPath assetPath, Checksum checksum, CancellationToken cancellationToken); public abstract Task GetAssetsAsync<T, TArg>(AssetPath assetPath, HashSet<Checksum> checksums, Action<Checksum, T, TArg>? callback, TArg? arg, CancellationToken cancellationToken); public async Task<SolutionInfo> CreateSolutionInfoAsync( Checksum solutionChecksum, SolutionServices solutionServices, CancellationToken cancellationToken) { var solutionCompilationChecksums = await GetAssetAsync<SolutionCompilationStateChecksums>(AssetPathKind.SolutionCompilationStateChecksums, solutionChecksum, cancellationToken).ConfigureAwait(false); var solutionChecksums = await GetAssetAsync<SolutionStateChecksums>(AssetPathKind.SolutionStateChecksums, solutionCompilationChecksums.SolutionState, cancellationToken).ConfigureAwait(false); var solutionAttributes = await GetAssetAsync<SolutionInfo.SolutionAttributes>(AssetPathKind.SolutionAttributes, solutionChecksums.Attributes, cancellationToken).ConfigureAwait(false); await GetAssetAsync<SourceGeneratorExecutionVersionMap>(AssetPathKind.SolutionSourceGeneratorExecutionVersionMap, solutionCompilationChecksums.SourceGeneratorExecutionVersionMap, cancellationToken).ConfigureAwait(false); // Fetch all the project state checksums up front. That allows getting all the data in a single call, and // enables parallel fetching of the projects below. using var _1 = ArrayBuilder<Task<ProjectInfo>>.GetInstance(solutionChecksums.Projects.Length, out var projectsTasks); await this.GetAssetHelper<ProjectStateChecksums>().GetAssetsAsync( AssetPathKind.ProjectStateChecksums, solutionChecksums.Projects.Checksums, static (_, projectStateChecksums, args) => { var (@this, projectsTasks, solutionServices, cancellationToken) = args; projectsTasks.Add(@this.CreateProjectInfoAsync(projectStateChecksums, solutionServices, cancellationToken)); }, (@this: this, projectsTasks, solutionServices, cancellationToken), cancellationToken).ConfigureAwait(false); // Deserialize the analyzer references, then wrap them in a new isolated analyzer reference set that has its own ALC var analyzerReference = await this.GetAssetsArrayAsync<AnalyzerReference>( AssetPathKind.SolutionAnalyzerReferences, solutionChecksums.AnalyzerReferences, cancellationToken).ConfigureAwait(false); var isolatedAnalyzerReferences = await IsolatedAnalyzerReferenceSet.CreateIsolatedAnalyzerReferencesAsync( useAsync: true, analyzerReference, solutionServices, cancellationToken).ConfigureAwait(false); var fallbackAnalyzerOptions = await GetAssetAsync<ImmutableDictionary<string, StructuredAnalyzerConfigOptions>>(AssetPathKind.SolutionFallbackAnalyzerOptions, solutionChecksums.FallbackAnalyzerOptions, cancellationToken).ConfigureAwait(false); // Fetch the projects in parallel. var projects = await Task.WhenAll(projectsTasks).ConfigureAwait(false); return SolutionInfo.Create( solutionAttributes.Id, solutionAttributes.Version, solutionAttributes.FilePath, ImmutableCollectionsMarshal.AsImmutableArray(projects), isolatedAnalyzerReferences, fallbackAnalyzerOptions).WithTelemetryId(solutionAttributes.TelemetryId); } public async Task<ProjectInfo> CreateProjectInfoAsync( ProjectStateChecksums projectChecksums, SolutionServices solutionServices, CancellationToken cancellationToken) { await Task.Yield(); var projectId = projectChecksums.ProjectId; var attributes = await GetAssetAsync<ProjectInfo.ProjectAttributes>(new(AssetPathKind.ProjectAttributes, projectId), projectChecksums.Info, cancellationToken).ConfigureAwait(false); Contract.ThrowIfFalse(RemoteSupportedLanguages.IsSupported(attributes.Language)); var compilationOptions = attributes.FixUpCompilationOptions( await GetAssetAsync<CompilationOptions>(new(AssetPathKind.ProjectCompilationOptions, projectId), projectChecksums.CompilationOptions, cancellationToken).ConfigureAwait(false)); var parseOptionsTask = GetAssetAsync<ParseOptions>(new(AssetPathKind.ProjectParseOptions, projectId), projectChecksums.ParseOptions, cancellationToken); var projectReferencesTask = this.GetAssetsArrayAsync<ProjectReference>(new(AssetPathKind.ProjectProjectReferences, projectId), projectChecksums.ProjectReferences, cancellationToken); var metadataReferencesTask = this.GetAssetsArrayAsync<MetadataReference>(new(AssetPathKind.ProjectMetadataReferences, projectId), projectChecksums.MetadataReferences, cancellationToken); var analyzerReferencesTask = this.GetAssetsArrayAsync<AnalyzerReference>(new(AssetPathKind.ProjectAnalyzerReferences, projectId), projectChecksums.AnalyzerReferences, cancellationToken); // Attempt to fetch all the documents for this project in bulk. This will allow for all the data to be fetched // efficiently. We can then go and create the DocumentInfos for each document in the project. await SynchronizeProjectDocumentsAsync(projectChecksums, cancellationToken).ConfigureAwait(false); var documentInfosTask = CreateDocumentInfosAsync(projectChecksums.Documents); var additionalDocumentInfosTask = CreateDocumentInfosAsync(projectChecksums.AdditionalDocuments); var analyzerConfigDocumentInfosTask = CreateDocumentInfosAsync(projectChecksums.AnalyzerConfigDocuments); // Deserialize the analyzer references, then wrap them in a new isolated analyzer reference set that has its own ALC. var isolatedAnalyzerReferencesTask = IsolatedAnalyzerReferenceSet.CreateIsolatedAnalyzerReferencesAsync( useAsync: true, await analyzerReferencesTask.ConfigureAwait(false), solutionServices, cancellationToken); return ProjectInfo.Create( attributes, compilationOptions, await parseOptionsTask.ConfigureAwait(false), await documentInfosTask.ConfigureAwait(false), await projectReferencesTask.ConfigureAwait(false), await metadataReferencesTask.ConfigureAwait(false), await isolatedAnalyzerReferencesTask.ConfigureAwait(false), await additionalDocumentInfosTask.ConfigureAwait(false), await analyzerConfigDocumentInfosTask.ConfigureAwait(false), hostObjectType: null); // TODO: https://github.com/dotnet/roslyn/issues/62804 async Task<ImmutableArray<DocumentInfo>> CreateDocumentInfosAsync(DocumentChecksumsAndIds checksumsAndIds) { var documentInfos = new FixedSizeArrayBuilder<DocumentInfo>(checksumsAndIds.Length); foreach (var (attributeChecksum, textChecksum, documentId) in checksumsAndIds) { cancellationToken.ThrowIfCancellationRequested(); documentInfos.Add(await CreateDocumentInfoAsync(documentId, attributeChecksum, textChecksum, cancellationToken).ConfigureAwait(false)); } return documentInfos.MoveToImmutable(); } } public async Task SynchronizeProjectDocumentsAsync( ProjectStateChecksums projectChecksums, CancellationToken cancellationToken) { await Task.Yield(); using var _1 = PooledHashSet<Checksum>.GetInstance(out var attributeChecksums); using var _2 = PooledHashSet<Checksum>.GetInstance(out var textChecksums); projectChecksums.Documents.AttributeChecksums.AddAllTo(attributeChecksums); projectChecksums.AdditionalDocuments.AttributeChecksums.AddAllTo(attributeChecksums); projectChecksums.AnalyzerConfigDocuments.AttributeChecksums.AddAllTo(attributeChecksums); projectChecksums.Documents.TextChecksums.AddAllTo(textChecksums); projectChecksums.AdditionalDocuments.TextChecksums.AddAllTo(textChecksums); projectChecksums.AnalyzerConfigDocuments.TextChecksums.AddAllTo(textChecksums); var attributesTask = this.GetAssetsAsync<DocumentInfo.DocumentAttributes>( assetPath: new(AssetPathKind.DocumentAttributes, projectChecksums.ProjectId), attributeChecksums, cancellationToken); var textTask = this.GetAssetsAsync<SerializableSourceText>( assetPath: new(AssetPathKind.DocumentText, projectChecksums.ProjectId), textChecksums, cancellationToken); await Task.WhenAll(attributesTask, textTask).ConfigureAwait(false); } public async Task<DocumentInfo> CreateDocumentInfoAsync( DocumentId documentId, Checksum attributeChecksum, Checksum textChecksum, CancellationToken cancellationToken) { var attributes = await GetAssetAsync<DocumentInfo.DocumentAttributes>(new(AssetPathKind.DocumentAttributes, documentId), attributeChecksum, cancellationToken).ConfigureAwait(false); var serializableSourceText = await GetAssetAsync<SerializableSourceText>(new(AssetPathKind.DocumentText, documentId), textChecksum, cancellationToken).ConfigureAwait(false); var textLoader = serializableSourceText.ToTextLoader(attributes.FilePath); // TODO: do we need version? return new DocumentInfo(attributes, textLoader, documentServiceProvider: null); } public AssetHelper<T> GetAssetHelper<T>() => new(this); public readonly struct AssetHelper<T>(AbstractAssetProvider assetProvider) { public Task GetAssetsAsync<TArg>(AssetPath assetPath, HashSet<Checksum> checksums, Action<Checksum, T, TArg>? callback, TArg? arg, CancellationToken cancellationToken) => assetProvider.GetAssetsAsync(assetPath, checksums, callback, arg, cancellationToken); public Task GetAssetsAsync<TArg>(AssetPath assetPath, ChecksumCollection checksums, Action<Checksum, T, TArg>? callback, TArg? arg, CancellationToken cancellationToken) => assetProvider.GetAssetsAsync(assetPath, checksums, callback, arg, cancellationToken); } }