Example #1
0
        public void TestRemoteWorkspaceCircularReferences()
        {
            using (var tempRoot = new Microsoft.CodeAnalysis.Test.Utilities.TempRoot())
            {
                var file = tempRoot.CreateDirectory().CreateFile("p1.dll");
                file.CopyContentFrom(typeof(object).Assembly.Location);

                var p1 = ProjectId.CreateNewId();
                var p2 = ProjectId.CreateNewId();

                var solutionInfo = SolutionInfo.Create(
                    SolutionId.CreateNewId(), VersionStamp.Create(), "",
                    new[]
                {
                    ProjectInfo.Create(
                        p1, VersionStamp.Create(), "p1", "p1", LanguageNames.CSharp, outputFilePath: file.Path,
                        projectReferences: new [] { new ProjectReference(p2) }),
                    ProjectInfo.Create(
                        p2, VersionStamp.Create(), "p2", "p2", LanguageNames.CSharp,
                        metadataReferences: new [] { MetadataReference.CreateFromFile(file.Path) })
                });

                var languages       = ImmutableHashSet.Create(LanguageNames.CSharp);
                var remoteWorkspace = new RemoteWorkspace(workspaceKind: "test");
                var optionService   = remoteWorkspace.Services.GetRequiredService <IOptionService>();
                var options         = new SerializableOptionSet(languages, optionService, ImmutableHashSet <IOption> .Empty, ImmutableDictionary <OptionKey, object> .Empty, ImmutableHashSet <OptionKey> .Empty);

                // this shouldn't throw exception
                remoteWorkspace.TryAddSolutionIfPossible(solutionInfo, workspaceVersion: 1, options, out var solution);
                Assert.NotNull(solution);
            }
        }
Example #2
0
        /// <summary>
        /// Adds an entire solution to the workspace, replacing any existing solution.
        /// </summary>
        internal bool TrySetCurrentSolution(
            SolutionInfo solutionInfo,
            int workspaceVersion,
            SerializableOptionSet options,
            [NotNullWhen(true)] out Solution?solution
            )
        {
            lock (_currentSolutionGate)
            {
                if (workspaceVersion <= _currentRemoteWorkspaceVersion)
                {
                    // we never move workspace backward
                    solution = null;
                    return(false);
                }

                // set initial solution version
                _currentRemoteWorkspaceVersion = workspaceVersion;

                // clear previous solution data if there is one
                // it is required by OnSolutionAdded
                ClearSolutionData();

                OnSolutionAdded(solutionInfo);

                SetOptions(options);

                solution = CurrentSolution;
                return(true);
            }
        }
        private SerializableOptionSet DeserializeOptionSet(ObjectReader reader, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var optionService = _workspaceServices.GetRequiredService <IOptionService>();

            return(SerializableOptionSet.Deserialize(reader, optionService, cancellationToken));
        }
Example #4
0
        public void SerializeOptionSet(
            SerializableOptionSet options,
            ObjectWriter writer,
            CancellationToken cancellationToken
            )
        {
            cancellationToken.ThrowIfCancellationRequested();

            options.Serialize(writer, cancellationToken);
        }
Example #5
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 #6
0
        public TemporaryWorkspace(
            HostServices hostServices,
            string?workspaceKind,
            SolutionInfo solutionInfo,
            SerializableOptionSet options
            ) : base(hostServices, workspaceKind)
        {
            SetOptions(Options.WithChangedOption(CacheOptions.RecoverableTreeLengthThreshold, 0));

            var documentOptionsProviderFactories = (
                (IMefHostExportProvider)Services.HostServices
                ).GetExports <IDocumentOptionsProviderFactory, OrderableMetadata>();

            RegisterDocumentOptionProviders(documentOptionsProviderFactories);

            OnSolutionAdded(solutionInfo);
            SetCurrentSolution(CurrentSolution.WithOptions(options));
        }
Example #7
0
 internal Solution(Workspace workspace, SolutionInfo.SolutionAttributes solutionAttributes, SerializableOptionSet options)
     : this(new SolutionState(workspace.PrimaryBranchId, new SolutionServices(workspace), solutionAttributes, options))
 {
 }
        /// <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 #9
0
        /// <summary>
        /// Adds an entire solution to the workspace, replacing any existing solution.
        /// </summary>
        public bool TryAddSolutionIfPossible(SolutionInfo solutionInfo, int workspaceVersion, SerializableOptionSet options, out Solution solution)
        {
            if (solutionInfo == null)
            {
                throw new ArgumentNullException(nameof(solutionInfo));
            }

            lock (_gate)
            {
                if (workspaceVersion <= _currentRemoteWorkspaceVersion)
                {
                    // we never move workspace backward
                    solution = null;
                    return(false);
                }

                // set initial solution version
                _currentRemoteWorkspaceVersion = workspaceVersion;

                // clear previous solution data if there is one
                // it is required by OnSolutionAdded
                this.ClearSolutionData();

                this.OnSolutionAdded(solutionInfo);

                SetOptions(options);

                solution = this.CurrentSolution;
                return(true);
            }
        }
Example #10
0
 public TemporaryWorkspace(SolutionInfo solutionInfo, SerializableOptionSet options) : this()
 {
     this.OnSolutionAdded(solutionInfo);
     this.SetCurrentSolution(this.CurrentSolution.WithOptions(options));
 }
Example #11
0
 public Solution CreateSolutionFromInfoAndOptions(SolutionInfo solutionInfo, SerializableOptionSet options)
 => _remoteWorkspace.CreateSolutionFromInfoAndOptions(solutionInfo, options);