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); } }
/// <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)); }
public void SerializeOptionSet( SerializableOptionSet options, ObjectWriter writer, CancellationToken cancellationToken ) { cancellationToken.ThrowIfCancellationRequested(); options.Serialize(writer, cancellationToken); }
/// <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; } }
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)); }
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; } }
/// <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); } }
public TemporaryWorkspace(SolutionInfo solutionInfo, SerializableOptionSet options) : this() { this.OnSolutionAdded(solutionInfo); this.SetCurrentSolution(this.CurrentSolution.WithOptions(options)); }
public Solution CreateSolutionFromInfoAndOptions(SolutionInfo solutionInfo, SerializableOptionSet options) => _remoteWorkspace.CreateSolutionFromInfoAndOptions(solutionInfo, options);