Esempio n. 1
0
        /// <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());
        }
Esempio n. 2
0
 /// <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);
     }
 }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
 /// <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)));
 }
Esempio n. 10
0
        /// <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);
        }
Esempio n. 11
0
 /// <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));
 }