private async Task <SolutionStateChecksums> ComputeChecksumsAsync(CancellationToken cancellationToken)
        {
            try
            {
                using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
                {
                    // get states by id order to have deterministic checksum
                    var orderedProjectIds    = ChecksumCache.GetOrCreate(ProjectIds, _ => ProjectIds.OrderBy(id => id.Id).ToImmutableArray());
                    var projectChecksumTasks = orderedProjectIds.Select(id => ProjectStates[id])
                                               .Where(s => RemoteSupportedLanguages.IsSupported(s.Language))
                                               .Select(s => s.GetChecksumAsync(cancellationToken));

                    var serializer      = _solutionServices.Workspace.Services.GetService <ISerializerService>();
                    var infoChecksum    = serializer.CreateChecksum(SolutionAttributes, cancellationToken);
                    var optionsChecksum = serializer.CreateChecksum(Options, cancellationToken);

                    var analyzerReferenceChecksums = ChecksumCache.GetOrCreate <AnalyzerReferenceChecksumCollection>(AnalyzerReferences,
                                                                                                                     _ => new AnalyzerReferenceChecksumCollection(AnalyzerReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));

                    var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);

                    return(new SolutionStateChecksums(infoChecksum, optionsChecksum, new ProjectChecksumCollection(projectChecksums), analyzerReferenceChecksums));
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        public static async Task <ImmutableArray <INamedTypeSymbol> > FindTypesAsync(
            INamedTypeSymbol type,
            Solution solution,
            IImmutableSet <Project>?projects,
            bool transitive,
            DependentTypesKind kind,
            CancellationToken cancellationToken)
        {
            if (SerializableSymbolAndProjectId.TryCreate(type, solution, cancellationToken, out var serializedType))
            {
                var client = await RemoteHostClient.TryGetClientAsync(solution.Workspace, cancellationToken).ConfigureAwait(false);

                if (client != null)
                {
                    var projectIds = projects?.Where(p => RemoteSupportedLanguages.IsSupported(p.Language)).SelectAsArray(p => p.Id) ?? default;

                    var result = await client.TryInvokeAsync <IRemoteDependentTypeFinderService, ImmutableArray <SerializableSymbolAndProjectId> >(
                        solution,
                        (service, solutionInfo, cancellationToken) => service.FindTypesAsync(solutionInfo, serializedType, projectIds, transitive, kind, cancellationToken),
                        cancellationToken).ConfigureAwait(false);

                    if (!result.HasValue)
                    {
                        return(ImmutableArray <INamedTypeSymbol> .Empty);
                    }

                    return(await RehydrateAsync(solution, result.Value, cancellationToken).ConfigureAwait(false));
                }

                // TODO: Do not fall back to in-proc https://github.com/dotnet/roslyn/issues/47557
            }

            return(await FindTypesInCurrentProcessAsync(type, solution, projects, transitive, kind, cancellationToken).ConfigureAwait(false));
        }
Example #3
0
        public async Task <ImmutableArray <AddImportFixData> > GetFixesAsync(
            Document document, TextSpan span, string diagnosticId, int maxResults, bool placeSystemNamespaceFirst,
            ISymbolSearchService symbolSearchService, bool searchReferenceAssemblies,
            ImmutableArray <PackageSource> packageSources, CancellationToken cancellationToken)
        {
            if (RemoteSupportedLanguages.IsSupported(document.Project.Language))
            {
                var callbackTarget = new RemoteSymbolSearchService(symbolSearchService, cancellationToken);
                var result         = await document.Project.Solution.TryRunCodeAnalysisRemoteAsync <IList <AddImportFixData> >(
                    callbackTarget,
                    nameof(IRemoteAddImportFeatureService.GetFixesAsync),
                    new object[]
                {
                    document.Id,
                    span,
                    diagnosticId,
                    maxResults,
                    placeSystemNamespaceFirst,
                    searchReferenceAssemblies,
                    packageSources
                },
                    cancellationToken).ConfigureAwait(false);

                if (result != null)
                {
                    return(result.ToImmutableArray());
                }
            }

            return(await GetFixesInCurrentProcessAsync(
                       document, span, diagnosticId, maxResults, placeSystemNamespaceFirst,
                       symbolSearchService, searchReferenceAssemblies,
                       packageSources, cancellationToken).ConfigureAwait(false));
        }
Example #4
0
        public static async Task <ImmutableArray <SerializableImportCompletionItem> > GetUnimportedExtensionMethodsAsync(
            Document document,
            int position,
            ITypeSymbol receiverTypeSymbol,
            ISet <string> namespaceInScope,
            bool forceIndexCreation,
            CancellationToken cancellationToken)
        {
            var ticks   = Environment.TickCount;
            var project = document.Project;

            // This service is only defined for C# and VB, but we'll be a bit paranoid.
            var client = RemoteSupportedLanguages.IsSupported(project.Language)
                ? await project.Solution.Workspace.TryGetRemoteHostClientAsync(cancellationToken).ConfigureAwait(false)
                : null;

            var(serializableItems, counter) = client == null
                ? await GetUnimportedExtensionMethodsInCurrentProcessAsync(document, position, receiverTypeSymbol, namespaceInScope, forceIndexCreation, cancellationToken).ConfigureAwait(false)
                : await GetUnimportedExtensionMethodsInRemoteProcessAsync(client, document, position, receiverTypeSymbol, namespaceInScope, forceIndexCreation, cancellationToken).ConfigureAwait(false);

            counter.TotalTicks = Environment.TickCount - ticks;
            counter.TotalExtensionMethodsProvided = serializableItems.Length;
            counter.Report();

            return(serializableItems);
        }
        public async Task FindAsync(
            SolutionState state,
            HashSet <Checksum> searchingChecksumsLeft,
            Dictionary <Checksum, object> result,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // verify input
            Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksum));
            Contract.ThrowIfFalse(this == stateChecksum);

            if (searchingChecksumsLeft.Remove(Checksum))
            {
                result[Checksum] = this;
            }

            if (searchingChecksumsLeft.Remove(Attributes))
            {
                result[Attributes] = state.SolutionAttributes;
            }

            if (searchingChecksumsLeft.Remove(Options))
            {
                result[Options] = state.Options;
            }

            if (searchingChecksumsLeft.Remove(Projects.Checksum))
            {
                result[Projects.Checksum] = Projects;
            }

            if (searchingChecksumsLeft.Remove(AnalyzerReferences.Checksum))
            {
                result[AnalyzerReferences.Checksum] = AnalyzerReferences;
            }

            foreach (var(_, projectState) in state.ProjectStates)
            {
                // solution state checksum can't be created without project state checksums created first
                // check unsupported projects
                if (!projectState.TryGetStateChecksums(out var projectStateChecksums))
                {
                    Contract.ThrowIfTrue(RemoteSupportedLanguages.IsSupported(projectState.Language));
                    continue;
                }

                await projectStateChecksums.FindAsync(projectState, searchingChecksumsLeft, result, cancellationToken).ConfigureAwait(false);

                if (searchingChecksumsLeft.Count == 0)
                {
                    break;
                }
            }

            ChecksumCollection.Find(state.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, result, cancellationToken);
        }
        private static async Task <RemoteHostClient> TryGetRemoteHostClientAsync(Project project, CancellationToken cancellationToken)
        {
            // This service is only defined for C# and VB, but we'll be a bit paranoid.
            if (!RemoteSupportedLanguages.IsSupported(project.Language))
            {
                return(null);
            }

            return(await project.Solution.Workspace.TryGetRemoteHostClientAsync(RemoteFeatureOptions.NavigateToEnabled, cancellationToken).ConfigureAwait(false));
        }
        public async Task <ProjectInfo> CreateProjectInfoAsync(Checksum projectChecksum, CancellationToken cancellationToken)
        {
            var projectChecksums = await GetAssetAsync <ProjectStateChecksums>(projectChecksum, cancellationToken).ConfigureAwait(false);

            var projectInfo = await GetAssetAsync <ProjectInfo.ProjectAttributes>(projectChecksums.Info, cancellationToken).ConfigureAwait(false);

            if (!RemoteSupportedLanguages.IsSupported(projectInfo.Language))
            {
                // only add project our workspace supports.
                // workspace doesn't allow creating project with unknown languages
                return(null);
            }

            var compilationOptions = projectInfo.FixUpCompilationOptions(
                await GetAssetAsync <CompilationOptions>(projectChecksums.CompilationOptions, cancellationToken).ConfigureAwait(false));

            var parseOptions = await GetAssetAsync <ParseOptions>(projectChecksums.ParseOptions, cancellationToken).ConfigureAwait(false);

            var projectReferences = await CreateCollectionAsync <ProjectReference>(projectChecksums.ProjectReferences, cancellationToken).ConfigureAwait(false);

            var metadataReferences = await CreateCollectionAsync <MetadataReference>(projectChecksums.MetadataReferences, cancellationToken).ConfigureAwait(false);

            var analyzerReferences = await CreateCollectionAsync <AnalyzerReference>(projectChecksums.AnalyzerReferences, cancellationToken).ConfigureAwait(false);

            var documentInfos = await CreateDocumentInfosAsync(projectChecksums.Documents, cancellationToken).ConfigureAwait(false);

            var additionalDocumentInfos = await CreateDocumentInfosAsync(projectChecksums.AdditionalDocuments, cancellationToken).ConfigureAwait(false);

            var analyzerConfigDocumentInfos = await CreateDocumentInfosAsync(projectChecksums.AnalyzerConfigDocuments, cancellationToken).ConfigureAwait(false);

            return(ProjectInfo.Create(
                       projectInfo.Id,
                       projectInfo.Version,
                       projectInfo.Name,
                       projectInfo.AssemblyName,
                       projectInfo.Language,
                       projectInfo.FilePath,
                       projectInfo.OutputFilePath,
                       compilationOptions,
                       parseOptions,
                       documentInfos,
                       projectReferences,
                       metadataReferences,
                       analyzerReferences,
                       additionalDocumentInfos,
                       projectInfo.IsSubmission)
                   .WithOutputRefFilePath(projectInfo.OutputRefFilePath)
                   .WithCompilationOutputFilePaths(projectInfo.CompilationOutputFilePaths)
                   .WithHasAllInformation(projectInfo.HasAllInformation)
                   .WithRunAnalyzers(projectInfo.RunAnalyzers)
                   .WithDefaultNamespace(projectInfo.DefaultNamespace)
                   .WithAnalyzerConfigDocuments(analyzerConfigDocumentInfos)
                   .WithTelemetryId(projectInfo.TelemetryId));
        }
Example #8
0
        private static async Task AppendAssetMapAsync(this Project project, Dictionary <Checksum, object> map, CancellationToken cancellationToken)
        {
            if (!RemoteSupportedLanguages.IsSupported(project.Language))
            {
                return;
            }

            var projectChecksums = await project.State.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false);

            projectChecksums.Find(project.State, Flatten(projectChecksums), map, cancellationToken);

            foreach (var document in project.Documents.Concat(project.AdditionalDocuments))
            {
                await document.AppendAssetMapAsync(map, cancellationToken).ConfigureAwait(false);
            }
        }
Example #9
0
        private async Task <SolutionStateChecksums> ComputeChecksumsAsync(CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
            {
                // get states by id order to have deterministic checksum
                var projectChecksumTasks = ProjectIds.Select(id => ProjectStates[id])
                                           .Where(s => RemoteSupportedLanguages.IsSupported(s.Language))
                                           .Select(s => s.GetChecksumAsync(cancellationToken));

                var serializer   = new Serializer(_solutionServices.Workspace);
                var infoChecksum = serializer.CreateChecksum(SolutionInfo.Attributes, cancellationToken);

                var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);

                return(new SolutionStateChecksums(infoChecksum, new ProjectChecksumCollection(projectChecksums)));
            }
        }
Example #10
0
        public void Find(
            SolutionState state,
            HashSet <Checksum> searchingChecksumsLeft,
            Dictionary <Checksum, object> result,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // verify input
            Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksum));
            Contract.ThrowIfFalse(this == stateChecksum);

            if (searchingChecksumsLeft.Remove(Checksum))
            {
                result[Checksum] = this;
            }

            if (searchingChecksumsLeft.Remove(Info))
            {
                result[Info] = state.SolutionAttributes;
            }

            if (searchingChecksumsLeft.Remove(Projects.Checksum))
            {
                result[Projects.Checksum] = Projects;
            }

            foreach (var kv in state.ProjectStates)
            {
                var projectState = kv.Value;

                // solution state checksum can't be created without project state checksums created first
                // check unsupported projects
                if (!projectState.TryGetStateChecksums(out var projectStateChecksums))
                {
                    Contract.ThrowIfTrue(RemoteSupportedLanguages.IsSupported(projectState.Language));
                    continue;
                }

                projectStateChecksums.Find(projectState, searchingChecksumsLeft, result, cancellationToken);
                if (searchingChecksumsLeft.Count == 0)
                {
                    return;
                }
            }
        }
Example #11
0
        /// <param name="projectsToInclude">Cone of projects to compute a checksum for.  Pass in <see langword="null"/>
        /// to get a checksum for the entire solution</param>
        private async Task <SolutionStateChecksums> ComputeChecksumsAsync(
            HashSet <ProjectId>?projectsToInclude,
            SerializableOptionSet options,
            CancellationToken cancellationToken)
        {
            try
            {
                using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
                {
                    // get states by id order to have deterministic checksum.  Limit to the requested set of projects
                    // if applicable.
                    var orderedProjectIds    = ChecksumCache.GetOrCreate(ProjectIds, _ => ProjectIds.OrderBy(id => id.Id).ToImmutableArray());
                    var projectChecksumTasks = orderedProjectIds.Where(id => projectsToInclude == null || projectsToInclude.Contains(id))
                                               .Select(id => ProjectStates[id])
                                               .Where(s => RemoteSupportedLanguages.IsSupported(s.Language))
                                               .Select(s => s.GetChecksumAsync(cancellationToken))
                                               .ToArray();

                    var serializer         = _solutionServices.Workspace.Services.GetRequiredService <ISerializerService>();
                    var attributesChecksum = serializer.CreateChecksum(SolutionAttributes, cancellationToken);

                    var optionsChecksum = serializer.CreateChecksum(options, cancellationToken);

                    var frozenSourceGeneratedDocumentIdentityChecksum = Checksum.Null;
                    var frozenSourceGeneratedDocumentTextChecksum     = Checksum.Null;

                    if (FrozenSourceGeneratedDocumentState != null)
                    {
                        frozenSourceGeneratedDocumentIdentityChecksum = serializer.CreateChecksum(FrozenSourceGeneratedDocumentState.Identity, cancellationToken);
                        frozenSourceGeneratedDocumentTextChecksum     = (await FrozenSourceGeneratedDocumentState.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false)).Text;
                    }

                    var analyzerReferenceChecksums = ChecksumCache.GetOrCreate <ChecksumCollection>(AnalyzerReferences,
                                                                                                    _ => new ChecksumCollection(AnalyzerReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));

                    var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);

                    return(new SolutionStateChecksums(attributesChecksum, optionsChecksum, new ChecksumCollection(projectChecksums), analyzerReferenceChecksums, frozenSourceGeneratedDocumentIdentityChecksum, frozenSourceGeneratedDocumentTextChecksum));
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
Example #12
0
        private (ImmutableHashSet <string> languages, SortedDictionary <OptionKey, (OptionValueKind, object?)> values) GetLanguagesAndValuesToSerialize(bool includeValues)
        {
            var valuesBuilder = new SortedDictionary <OptionKey, (OptionValueKind, object?)>(OptionKeyComparer.Instance);
            var languages     = ImmutableHashSet <string> .Empty;

            foreach (var(optionKey, value) in _serializableOptionValues)
            {
                Debug.Assert(ShouldSerialize(optionKey));

                Debug.Assert(!optionKey.Option.IsPerLanguage || RemoteSupportedLanguages.IsSupported(optionKey.Language));
                if (optionKey.Language != null)
                {
                    languages = languages.Add(optionKey.Language);
                }

                if (includeValues)
                {
                    OptionValueKind kind;
                    switch (value)
                    {
                    case ICodeStyleOption:
                        if (optionKey.Option.Type.GenericTypeArguments.Length != 1)
                        {
                            continue;
                        }

                        kind = OptionValueKind.CodeStyleOption;
                        break;

                    case NamingStylePreferences:
                        kind = OptionValueKind.NamingStylePreferences;
                        break;

                    default:
                        kind = value != null && value.GetType().IsEnum ? OptionValueKind.Enum : OptionValueKind.Object;
                        break;
                    }

                    valuesBuilder.Add(optionKey, (kind, value));
                }
            }

            return(languages, valuesBuilder);
        }
        private async Task <SolutionStateChecksums> ComputeChecksumsAsync(CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
            {
                // get states by id order to have deterministic checksum
                var orderedProjectIds    = ChecksumCache.GetOrCreate(ProjectIds, _ => ProjectIds.OrderBy(id => id.Id).ToImmutableArray());
                var projectChecksumTasks = orderedProjectIds.Select(id => ProjectStates[id])
                                           .Where(s => RemoteSupportedLanguages.IsSupported(s.Language))
                                           .Select(s => s.GetChecksumAsync(cancellationToken));

                var serializer      = _solutionServices.Workspace.Services.GetService <ISerializerService>();
                var infoChecksum    = serializer.CreateChecksum(SolutionAttributes, cancellationToken);
                var optionsChecksum = serializer.CreateChecksum(Options, cancellationToken);

                var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);

                return(new SolutionStateChecksums(infoChecksum, optionsChecksum, new ProjectChecksumCollection(projectChecksums)));
            }
        }
Example #14
0
        private static void AppendAssetMap(Project project, Dictionary <Checksum, object> map)
        {
            if (!project.State.TryGetStateChecksums(out var projectChecksums))
            {
                Debug.Assert(!RemoteSupportedLanguages.IsSupported(project.Language));
                return;
            }

            projectChecksums.Find(project.State, Flatten(projectChecksums), map, CancellationToken.None);

            foreach (var document in project.Documents)
            {
                AppendAssetMap(document, map);
            }

            foreach (var document in project.AdditionalDocuments)
            {
                AppendAssetMap(document, map);
            }
        }
        private static async Task <(bool, ImmutableArray <SymbolAndProjectId>)> TryFindAllDeclarationsWithNormalQueryInRemoteProcessAsync(
            Project project, SearchQuery query, SymbolFilter criteria, CancellationToken cancellationToken)
        {
            if (!RemoteSupportedLanguages.IsSupported(project.Language))
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var result = await project.Solution.TryRunCodeAnalysisRemoteAsync <IList <SerializableSymbolAndProjectId> >(
                nameof(IRemoteSymbolFinder.FindAllDeclarationsWithNormalQueryAsync),
                new object[] { project.Id, query.Name, query.Kind, criteria }, cancellationToken).ConfigureAwait(false);

            if (result == null)
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var rehydrated = await RehydrateAsync(
                project.Solution, result, cancellationToken).ConfigureAwait(false);

            return(true, rehydrated);
        }
Example #16
0
        private static async Task <(bool succeeded, ImmutableArray <SymbolAndProjectId> results)> TryFindSourceDeclarationsWithPatternInRemoteProcessAsync(
            Project project, string pattern, SymbolFilter criteria, CancellationToken cancellationToken)
        {
            if (!RemoteSupportedLanguages.IsSupported(project.Language))
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var result = await project.Solution.TryRunCodeAnalysisRemoteAsync <IList <SerializableSymbolAndProjectId> >(
                nameof(IRemoteSymbolFinder.FindProjectSourceDeclarationsWithPatternAsync),
                new object[] { project.Id, pattern, criteria }, cancellationToken).ConfigureAwait(false);

            if (result == null)
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var rehydrated = await RehydrateAsync(
                project.Solution, result, cancellationToken).ConfigureAwait(false);

            return(true, rehydrated);
        }
        private static async Task <(bool, ImmutableArray <SymbolAndProjectId>)> TryFindSourceDeclarationsWithNormalQueryInRemoteProcessAsync(
            Project project, string name, bool ignoreCase, SymbolFilter criteria, CancellationToken cancellationToken)
        {
            if (!RemoteSupportedLanguages.IsSupported(project.Language))
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var result = await project.Solution.TryRunCodeAnalysisRemoteAsync <ImmutableArray <SerializableSymbolAndProjectId> >(
                RemoteFeatureOptions.SymbolFinderEnabled,
                nameof(IRemoteSymbolFinder.FindProjectSourceDeclarationsWithNormalQueryAsync),
                new object[] { project.Id, name, ignoreCase, criteria }, cancellationToken).ConfigureAwait(false);

            if (result.IsDefault)
            {
                return(false, ImmutableArray <SymbolAndProjectId> .Empty);
            }

            var rehydrated = await RehydrateAsync(
                project.Solution, result, cancellationToken).ConfigureAwait(false);

            return(true, rehydrated);
        }
Example #18
0
        public void Serialize(ObjectWriter writer, CancellationToken cancellationToken)
        {
            // We serialize the following contents from this option set:
            //  1. Languages
            //  2. Prefetched serializable option key-value pairs
            //  3. Changed option keys.

            // NOTE: keep the serialization in sync with Deserialize method below.
            // NOTE: keep this in sync with GetDebugString above.

            cancellationToken.ThrowIfCancellationRequested();

            var(languages, values) = this.GetLanguagesAndValuesToSerialize(includeValues: true);

            writer.WriteInt32(languages.Count);
            foreach (var language in languages.Order())
            {
                Debug.Assert(RemoteSupportedLanguages.IsSupported(language));
                writer.WriteString(language);
            }

            writer.WriteInt32(values.Count);
            foreach (var(optionKey, (kind, value)) in values)
            {
                SerializeOptionKey(optionKey);

                writer.WriteInt32((int)kind);
                if (kind == OptionValueKind.Enum)
                {
                    RoslynDebug.Assert(value != null);
                    writer.WriteInt32((int)value);
                }
                else if (kind is OptionValueKind.CodeStyleOption or OptionValueKind.NamingStylePreferences)
                {
                    RoslynDebug.Assert(value != null);
                    ((IObjectWritable)value).WriteTo(writer);
                }
Example #19
0
 private bool ShouldSerialize(OptionKey optionKey)
 => _serializableOptionValues.ContainsKey(optionKey) &&
 (!optionKey.Option.IsPerLanguage || RemoteSupportedLanguages.IsSupported(optionKey.Language));
        /// <param name="projectsToInclude">Cone of projects to compute a checksum for.  Pass in <see langword="null"/>
        /// to get a checksum for the entire solution</param>
        private async Task <SolutionStateChecksums> ComputeChecksumsAsync(
            HashSet <ProjectId>?projectsToInclude,
            SerializableOptionSet options,
            CancellationToken cancellationToken)
        {
            try
            {
                using (Logger.LogBlock(FunctionId.SolutionState_ComputeChecksumsAsync, FilePath, cancellationToken))
                {
                    // get states by id order to have deterministic checksum.  Limit expensive computation to the
                    // requested set of projects if applicable.
                    var orderedProjectIds    = ChecksumCache.GetOrCreate(ProjectIds, _ => ProjectIds.OrderBy(id => id.Id).ToImmutableArray());
                    var projectChecksumTasks = orderedProjectIds
                                               .Select(id => (state: ProjectStates[id], mustCompute: projectsToInclude == null || projectsToInclude.Contains(id)))
                                               .Where(t => RemoteSupportedLanguages.IsSupported(t.state.Language))
                                               .Select(async t =>
                    {
                        // if it's a project that's specifically in the sync'ed cone, include this checksum so that
                        // this project definitely syncs over.
                        if (t.mustCompute)
                        {
                            return(await t.state.GetChecksumAsync(cancellationToken).ConfigureAwait(false));
                        }

                        // If it's a project that is not in the cone, still try to get the latest checksum for it if
                        // we have it.  That way we don't send over a checksum *without* that project, causing the
                        // OOP side to throw that project away (along with all the compilation info stored with it).
                        if (t.state.TryGetStateChecksums(out var stateChecksums))
                        {
                            return(stateChecksums.Checksum);
                        }

                        // We have never computed the checksum for this project.  Don't send anything for it.
                        return(null);
                    })
                                               .ToArray();

                    var serializer         = _solutionServices.Workspace.Services.GetRequiredService <ISerializerService>();
                    var attributesChecksum = serializer.CreateChecksum(SolutionAttributes, cancellationToken);

                    var optionsChecksum = serializer.CreateChecksum(options, cancellationToken);

                    var frozenSourceGeneratedDocumentIdentityChecksum = Checksum.Null;
                    var frozenSourceGeneratedDocumentTextChecksum     = Checksum.Null;

                    if (FrozenSourceGeneratedDocumentState != null)
                    {
                        frozenSourceGeneratedDocumentIdentityChecksum = serializer.CreateChecksum(FrozenSourceGeneratedDocumentState.Identity, cancellationToken);
                        frozenSourceGeneratedDocumentTextChecksum     = (await FrozenSourceGeneratedDocumentState.GetStateChecksumsAsync(cancellationToken).ConfigureAwait(false)).Text;
                    }

                    var analyzerReferenceChecksums = ChecksumCache.GetOrCreate <ChecksumCollection>(AnalyzerReferences,
                                                                                                    _ => new ChecksumCollection(AnalyzerReferences.Select(r => serializer.CreateChecksum(r, cancellationToken)).ToArray()));

                    var projectChecksums = await Task.WhenAll(projectChecksumTasks).ConfigureAwait(false);

                    return(new SolutionStateChecksums(
                               attributesChecksum,
                               optionsChecksum,
                               new ChecksumCollection(projectChecksums.WhereNotNull().ToArray()),
                               analyzerReferenceChecksums,
                               frozenSourceGeneratedDocumentIdentityChecksum,
                               frozenSourceGeneratedDocumentTextChecksum));
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
Example #21
0
        public async Task FindAsync(
            SolutionState state,
            HashSet <Checksum> searchingChecksumsLeft,
            Dictionary <Checksum, object> result,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // verify input
            Contract.ThrowIfFalse(state.TryGetStateChecksums(out var stateChecksum));
            Contract.ThrowIfFalse(this == stateChecksum);

            if (searchingChecksumsLeft.Remove(Checksum))
            {
                result[Checksum] = this;
            }

            if (searchingChecksumsLeft.Remove(Attributes))
            {
                result[Attributes] = state.SolutionAttributes;
            }

            if (searchingChecksumsLeft.Remove(Options))
            {
                result[Options] = state.Options;
            }

            if (searchingChecksumsLeft.Remove(FrozenSourceGeneratedDocumentIdentity))
            {
                Contract.ThrowIfNull(state.FrozenSourceGeneratedDocumentState, "We should not have had a FrozenSourceGeneratedDocumentIdentity checksum if we didn't have a text in the first place.");
                result[FrozenSourceGeneratedDocumentIdentity] = state.FrozenSourceGeneratedDocumentState.Identity;
            }

            if (searchingChecksumsLeft.Remove(FrozenSourceGeneratedDocumentText))
            {
                Contract.ThrowIfNull(state.FrozenSourceGeneratedDocumentState, "We should not have had a FrozenSourceGeneratedDocumentState checksum if we didn't have a text in the first place.");
                result[FrozenSourceGeneratedDocumentText] = await SerializableSourceText.FromTextDocumentStateAsync(state.FrozenSourceGeneratedDocumentState, cancellationToken).ConfigureAwait(false);
            }

            if (searchingChecksumsLeft.Remove(Projects.Checksum))
            {
                result[Projects.Checksum] = Projects;
            }

            if (searchingChecksumsLeft.Remove(AnalyzerReferences.Checksum))
            {
                result[AnalyzerReferences.Checksum] = AnalyzerReferences;
            }

            foreach (var(_, projectState) in state.ProjectStates)
            {
                // solution state checksum can't be created without project state checksums created first
                // check unsupported projects
                if (!projectState.TryGetStateChecksums(out var projectStateChecksums))
                {
                    Contract.ThrowIfTrue(RemoteSupportedLanguages.IsSupported(projectState.Language));
                    continue;
                }

                await projectStateChecksums.FindAsync(projectState, searchingChecksumsLeft, result, cancellationToken).ConfigureAwait(false);

                if (searchingChecksumsLeft.Count == 0)
                {
                    break;
                }
            }

            ChecksumCollection.Find(state.AnalyzerReferences, AnalyzerReferences, searchingChecksumsLeft, result, cancellationToken);
        }
Example #22
0
        public string GetDebugString()
        {
            // NOTE: keep this in sync with Serialize below.

            using var _ = PooledStringBuilder.GetInstance(out var sb);

            var(languages, values) = this.GetLanguagesAndValuesToSerialize(includeValues: true);

            sb.AppendLine($"languages count: {languages.Count}");
            foreach (var language in languages.Order())
            {
                Debug.Assert(RemoteSupportedLanguages.IsSupported(language));
                sb.AppendLine(language);
            }

            sb.AppendLine();
            sb.AppendLine($"values count: {values.Count}");
            foreach (var(optionKey, (kind, value)) in values)
            {
                SerializeOptionKey(optionKey);

                sb.Append($"{kind}: ");
                if (kind == OptionValueKind.Enum)
                {
                    RoslynDebug.Assert(value != null);
                    sb.AppendLine(value.ToString());
                }
                else if (kind is OptionValueKind.CodeStyleOption)
                {
                    RoslynDebug.Assert(value != null);
                    var codeStyleOption = (ICodeStyleOption)value;
                    sb.AppendLine(codeStyleOption.ToXElement().ToString());
                }
                else if (kind is OptionValueKind.NamingStylePreferences)
                {
                    RoslynDebug.Assert(value != null);
                    var namingStylePreferences = (NamingStylePreferences)value;
                    sb.AppendLine(namingStylePreferences.CreateXElement().ToString());
                }
                else
                {
                    sb.AppendLine($"{value}");
                }

                sb.AppendLine();
            }

            sb.AppendLine();
            sb.AppendLine($"changed options count: {_changedOptionKeysSerializable.Count}");
            foreach (var changedKey in _changedOptionKeysSerializable.OrderBy(OptionKeyComparer.Instance))
            {
                SerializeOptionKey(changedKey);
            }

            return(sb.ToString());

            void SerializeOptionKey(OptionKey optionKey)
            {
                Debug.Assert(ShouldSerialize(optionKey));

                sb.AppendLine($"{optionKey.Option.Name} {optionKey.Option.Feature} {optionKey.Option.IsPerLanguage} {optionKey.Language}");
            }
        }