public static CompilationTranslationAction ProjectParseOptions(ProjectState state) { return(new ProjectParseOptionsAction(state)); }
/// <summary> /// Attempts to get (without waiting) a metadata reference to a possibly in progress /// compilation. Only actual compilation references are returned. Could potentially /// return null if nothing can be provided. /// </summary> public MetadataReference GetPartialMetadataReference(SolutionState solution, ProjectState fromProject, ProjectReference projectReference, CancellationToken cancellationToken) { var state = this.ReadState(); // get compilation in any state it happens to be in right now. if (state.Compilation.TryGetValue(out var compilation) && compilation != null && this.ProjectState.LanguageServices == fromProject.LanguageServices) { // if we have a compilation and its the correct language, use a simple compilation reference return(compilation.ToMetadataReference(projectReference.Aliases, projectReference.EmbedInteropTypes)); } return(null); }
private static string LogBuildCompilationAsync(ProjectState state) { return(string.Join(",", state.AssemblyName, state.DocumentIds.Count)); }
/// <summary> /// Creates a tracker for the provided project. The tracker will be in the 'empty' state /// and will have no extra information beyond the project itself. /// </summary> public CompilationTracker(ProjectState project) : this(project, State.Empty) { }
/// <summary> /// Tries to get the latest snapshot of the compilation without waiting for it to be /// fully built. This method takes advantage of the progress side-effect produced during /// <see cref="BuildCompilationInfoAsync(SolutionState, CancellationToken)"/>. It will either return the already built compilation, any /// in-progress compilation or any known old compilation in that order of preference. /// The compilation state that is returned will have a compilation that is retained so /// that it cannot disappear. /// </summary> private void GetPartialCompilationState( SolutionState solution, DocumentId id, out ProjectState inProgressProject, out Compilation inProgressCompilation, CancellationToken cancellationToken) { var state = this.ReadState(); inProgressCompilation = state.Compilation.GetValue(cancellationToken); // check whether we can bail out quickly for typing case var inProgressState = state as InProgressState; // all changes left for this document is modifying the given document. // we can use current state as it is since we will replace the document with latest document anyway. if (inProgressState != null && inProgressCompilation != null && inProgressState.IntermediateProjects.All(t => IsTouchDocumentActionForDocument(t, id))) { inProgressProject = this.ProjectState; SolutionLogger.UseExistingPartialProjectState(); return; } inProgressProject = inProgressState != null?inProgressState.IntermediateProjects.First().Item1 : this.ProjectState; // if we already have a final compilation we are done. if (inProgressCompilation != null && state is FinalState) { SolutionLogger.UseExistingFullProjectState(); return; } // 1) if we have an in-progress compilation use it. // 2) If we don't, then create a simple empty compilation/project. // 3) then, make sure that all it's p2p refs and whatnot are correct. if (inProgressCompilation == null) { inProgressProject = inProgressProject.RemoveAllDocuments(); inProgressCompilation = this.CreateEmptyCompilation(); } // first remove all project from the project and compilation. inProgressProject = inProgressProject.WithProjectReferences(ImmutableArray.Create <ProjectReference>()); // Now add in back a consistent set of project references. For project references // try to get either a CompilationReference or a SkeletonReference. This ensures // that the in-progress project only reports a reference to another project if it // could actually get a reference to that project's metadata. var metadataReferences = new List <MetadataReference>(); var newProjectReferences = new List <ProjectReference>(); metadataReferences.AddRange(this.ProjectState.MetadataReferences); var metadataReferenceToProjectId = new Dictionary <MetadataReference, ProjectId>(); foreach (var projectReference in this.ProjectState.ProjectReferences) { var referencedProject = solution.GetProjectState(projectReference.ProjectId); if (referencedProject != null) { if (referencedProject.IsSubmission) { var compilation = solution.GetCompilationAsync(projectReference.ProjectId, cancellationToken).WaitAndGetResult(cancellationToken); inProgressCompilation = inProgressCompilation.WithScriptCompilationInfo(inProgressCompilation.ScriptCompilationInfo.WithPreviousScriptCompilation(compilation)); } else { // get the latest metadata for the partial compilation of the referenced project. var metadata = solution.GetPartialMetadataReference(projectReference, this.ProjectState, cancellationToken); if (metadata == null) { // if we failed to get the metadata, check to see if we previously had existing metadata and reuse it instead. var inProgressCompilationNotRef = inProgressCompilation; metadata = inProgressCompilationNotRef.ExternalReferences.FirstOrDefault( r => solution.GetProjectState(inProgressCompilationNotRef.GetAssemblyOrModuleSymbol(r) as IAssemblySymbol, cancellationToken)?.Id == projectReference.ProjectId); } if (metadata != null) { newProjectReferences.Add(projectReference); metadataReferences.Add(metadata); metadataReferenceToProjectId.Add(metadata, projectReference.ProjectId); } } } } inProgressProject = inProgressProject.AddProjectReferences(newProjectReferences); inProgressCompilation = UpdateCompilationWithNewReferencesAndRecordAssemblySymbols(inProgressCompilation, metadataReferences, metadataReferenceToProjectId); SolutionLogger.CreatePartialProjectState(); }