/// <summary> /// Filter a workspace definition. /// </summary> public List <ModuleDefinition> FilterWorkspaceDefinition( [NotNull] WorkspaceDefinition workspace, [NotNull] EvaluationFilter evaluationFilter, [NotNull] ISpecDependencyProvider provider) { // Resulting list should always have a prelude. var modulesToInclude = new HashSet <ModuleDefinition> { workspace.PreludeModule }; // Getting all the files relevant to the build. var filesToInclude = GetFilesToInclude(modulesToInclude, workspace, provider, evaluationFilter); // Keep modules with a set of files relevant for a given filter. var partiallyFilteredModules = new Dictionary <ModuleDefinition, HashSet <AbsolutePath> >(); foreach (var kvp in workspace.Specs) { // File is not part of 'must have' module and is part of 'must have' spec. if (filesToInclude.Contains(kvp.Path)) { var map = partiallyFilteredModules.GetOrAdd(kvp.OwningModule, k => new HashSet <AbsolutePath>()); map.Add(kvp.Path); } } foreach (var kvp in partiallyFilteredModules) { var moduleDefinition = kvp.Key.WithSpecs(kvp.Value.ToReadOnlySet()); modulesToInclude.Add(moduleDefinition); } return(modulesToInclude.ToList()); }
/// <summary> /// Computes the transitive closure of all dependents of the changed specs and report them as 'dirty' to the artifact manager, /// so they are not replaced by their public facade version and their serialized AST is not used /// </summary> private void NotifyDirtySpecsForPublicFacadeAndAstReuse(ISpecDependencyProvider snapshotProvider, WorkspaceDefinition workspaceDefinition, IReadOnlyList <AbsolutePath> changedSpecs) { if (CanUseSpecPublicFacadeAndAst()) { var changedSpecsWithDependents = snapshotProvider.ComputeReflectiveClosureOfDependentFiles(changedSpecs); FrontEndArtifactManager.NotifySpecsCannotBeUsedAsFacades(changedSpecsWithDependents); var requiredSpecs = snapshotProvider.ComputeReflectiveClosureOfDependencyFiles(changedSpecsWithDependents); Logger.ReportDestructionCone(LoggingContext, changedSpecs.Count, changedSpecsWithDependents.Count, requiredSpecs.Count, workspaceDefinition.SpecCount); } }
private HashSet <ParsedModule> GetModulesToInclude(Workspace workspace, ISpecDependencyProvider provider, EvaluationFilter evaluationFilter) { var modulesToResolve = new HashSet <string>(evaluationFilter.ModulesToResolve.Select(s => s.ToString(m_pathTable.StringTable))); // Getting all the modules specified via filter var modulesToInclude = workspace.SpecModules.Where(m => modulesToResolve.Contains(m.Descriptor.Name)).ToHashSet(); // Getting all upstream dependencis for all modules. modulesToInclude = TransitiveClosureOfAllRelevantModules(modulesToInclude, workspace, provider); return(modulesToInclude); }
private static void AddUpStreamDependencies( HashSet <AbsolutePath> resultingSet, AbsolutePath specPath, ISpecDependencyProvider provider) { var dependencies = provider.GetFileDependenciesOf(specPath); foreach (var path in dependencies) { if (resultingSet.Add(path)) { // We've just added new file to a closure. // Need to add their dependencies as well. AddUpStreamDependencies(resultingSet, path, provider); } } }
private static HashSet <ParsedModule> TransitiveClosureOfAllRelevantModules(IEnumerable <ParsedModule> modules, Workspace workspace, ISpecDependencyProvider provider) { var modulesByName = workspace.SpecModules.ToDictionary(m => m.Descriptor.Name); HashSet <ParsedModule> result = new HashSet <ParsedModule>(modules); foreach (var module in modules) { result.AddRange(GetUpStreamModuleNames(module, provider).Select(name => modulesByName[name])); } return(result); }
private static HashSet <string> GetUpStreamModuleNames(ParsedModule parsedModule, ISpecDependencyProvider semanticModel) { HashSet <string> upStreamDependencies = new HashSet <string>(); foreach (var spec in parsedModule.Specs) { upStreamDependencies.AddRange(semanticModel.GetModuleDependenciesOf(spec.Key)); } return(upStreamDependencies); }
private HashSet <AbsolutePath> GetFilesToInclude(HashSet <ParsedModule> modulesToInclude, Workspace workspace, ISpecDependencyProvider provider, EvaluationFilter evaluationFilter) { // TODO: merge two 'GetFilesToInclude' methods into one. var filesToInclude = new HashSet <AbsolutePath>(); foreach (var kvp in workspace.SpecSources) { var parsedSpec = kvp.Key; // If the spec belonged to a module that is required, then the entire module will be evaluated. // No need to keep the spec separately if (!modulesToInclude.Contains(kvp.Value.OwningModule)) { foreach (var specRootToResolve in evaluationFilter.ValueDefinitionRootsToResolve) { if (parsedSpec == specRootToResolve || parsedSpec.IsWithin(m_pathTable, specRootToResolve)) { filesToInclude.Add(parsedSpec); AddUpStreamDependencies(filesToInclude, kvp.Key, provider); } } } } return(filesToInclude); }
private HashSet <AbsolutePath> GetFilesToInclude(HashSet <ModuleDefinition> modulesToInclude, WorkspaceDefinition workspace, ISpecDependencyProvider provider, EvaluationFilter evaluationFilter) { var filesToInclude = new HashSet <AbsolutePath>(); foreach (var kvp in workspace.Specs) { var specPath = kvp.Path; // If the spec belonged to a module that is required, then the entire module will be evaluated. // No need to keep the spec separately if (!modulesToInclude.Contains(kvp.OwningModule)) { foreach (var specRootToResolve in evaluationFilter.ValueDefinitionRootsToResolve) { if (specPath == specRootToResolve || specPath.IsWithin(m_pathTable, specRootToResolve)) { filesToInclude.Add(specPath); AddUpStreamDependencies(filesToInclude, specPath, provider); } } } } return(filesToInclude); }
/// <summary> /// Computes reflective transitive closure all dependency files starting from <paramref name="roots"/> /// </summary> public static HashSet <AbsolutePath> ComputeReflectiveClosureOfDependencyFiles(this ISpecDependencyProvider provider, IEnumerable <AbsolutePath> roots, HashSet <AbsolutePath> closureSoFar) { return(ComputeReflectiveClosure(closureSoFar, roots, provider, (provider2, path) => provider2.GetFileDependenciesOf(path))); }
/// <summary> /// Functional variant of <see cref="ComputeReflectiveClosureOfDependencyFiles(ISpecDependencyProvider, IEnumerable{AbsolutePath}, HashSet{AbsolutePath})"/>. /// </summary> public static HashSet <AbsolutePath> ComputeReflectiveClosureOfDependencyFiles(this ISpecDependencyProvider provider, IEnumerable <AbsolutePath> roots) { var result = new HashSet <AbsolutePath>(); ComputeReflectiveClosureOfDependencyFiles(provider, roots, result); return(result); }
/// <summary> /// Computes reflective transitive closure all dependent files starting from <paramref name="roots"/> /// </summary> public static void ComputeReflectiveClosureOfDependentFiles(this ISpecDependencyProvider provider, IEnumerable <AbsolutePath> roots, HashSet <AbsolutePath> result) { ComputeReflectiveClosure(result, roots, provider, (provider2, path) => provider2.GetFileDependentsOf(path)); }