예제 #1
0
        public void create_a_merged_workspace_filter()
        {
            var workspace1 = new WorkspaceFilter();

            workspace1.AddFilter(new FixtureFilter()
            {
                Name = typeof(MathFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            var workspace2 = new WorkspaceFilter();

            workspace2.AddFilter(new FixtureFilter()
            {
                Name = typeof(AnotherFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            var combined = new WorkspaceFilter(new WorkspaceFilter[] { workspace1, workspace2 });

            var filter = combined.CreateTypeFilter();

            filter.Matches(typeof(MathFixture)).ShouldBeTrue();

            filter.Matches(typeof(AnotherFixture)).ShouldBeTrue();

            filter.Matches(GetType()).ShouldBeFalse();
        }
예제 #2
0
 public WorkspaceSuite(string name) : base(name)
 {
     Filter = new WorkspaceFilter()
     {
         Name = name
     };
 }
예제 #3
0
 public WorkspaceSuite(string name)
     : base(name)
 {
     Filter = new WorkspaceFilter()
     {
         Name = name
     };
 }
예제 #4
0
        public void workspace_filter_returns_always_when_it_has_no_explicit_filters()
        {
            var workspace = new WorkspaceFilter();

            workspace.FilterCount.ShouldEqual(0);

            workspace.Filters.ShouldHaveTheSameElementsAs(FixtureFilter.All());
        }
        public IEnumerable<IFixtureSelector> Organize(FixtureLibrary library, WorkspaceFilter workspace)
        {
            var namespaces = new Cache<string, NamespaceSelector>(ns => new NamespaceSelector(ns));
            var fixtures = new Cache<string, FixtureSelector>();

            // pass #1, collate the namespaces
            string[] names = getAllNamespaces(library, namespaces);

            var topLevels = collateNamespaces(namespaces, names);
            buildFixtureSelectors(library, namespaces, fixtures);

            selectFixtures(fixtures, workspace);
            selectNamespaces(namespaces, workspace);

            namespaces.Each(x => x.SetInitialState());

            return topLevels.ToArray();
        }
예제 #6
0
        /// <summary>
        /// Filters a <paramref name="workspace"/> using <paramref name="modules"/>.
        /// </summary>
        /// <remarks>
        /// Currently only module filter is supported.
        /// </remarks>
        private WorkspaceDefinition ApplyModuleFilter(WorkspaceDefinition workspace, IReadOnlyList <StringId> modules)
        {
            using (var sw = Watch.Start())
            {
                // WorkspaceFilter updates the existing workspace instead of creating brand new one.
                // This is crucial to avoid redundant type checking required for semantic workspace creation.
                var filter = new WorkspaceFilter(FrontEndContext.PathTable);
                WorkspaceDefinition filteredDefinition = filter.ApplyModuleFilter(workspace, modules);

                Logger.WorkspaceDefinitionFilteredBasedOnModuleFilter(LoggingContext,
                                                                      workspace.ModuleCount - filteredDefinition.ModuleCount,
                                                                      workspace.SpecCount - filteredDefinition.SpecCount,
                                                                      workspace.ModuleCount,
                                                                      filteredDefinition.ModuleCount,
                                                                      sw.ElapsedMilliseconds);
                return(filteredDefinition);
            }
        }
예제 #7
0
        public void can_serialize_and_deserialize_a_workspace_filter()
        {
            var workspace = new WorkspaceFilter();

            workspace.AddFilter(new FixtureFilter()
            {
                Name = typeof(MathFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            workspace.AddFilter(new FixtureFilter()
            {
                Name = typeof(AnotherFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            workspace.ShouldBeSerializable().ShouldBeOfType <WorkspaceFilter>().FilterCount.ShouldEqual(2);
        }
예제 #8
0
        private List <ModuleDefinition> GetModulesAndSpecsToEvaluate(EvaluationFilter evaluationFilter)
        {
            if (
                // Module filter can be applied without /enableIncrementalFrontEnd+
                evaluationFilter.ModulesToResolve.Count != 0 ||
                (evaluationFilter.CanPerformPartialEvaluationScript(PrimaryConfigFile) && FrontEndConfiguration.EnableIncrementalFrontEnd()))
            {
                var workspaceFilter = new WorkspaceFilter(FrontEndContext.PathTable);
                return(workspaceFilter.FilterForEvaluation(Workspace, evaluationFilter));
            }

            // The prelude is never part of the build extent
            var allModules = Workspace.SpecModules.ToList();

            // Under an Office build, the default source resolver defines the build extent. Otherwise, all modules are used
            var moduleExtent = FrontEndConfiguration.UseLegacyOfficeLogic() ? FindModulesConstitutingLegacyBuildExtent(allModules) : allModules;

            return(moduleExtent.Select(m => m.Definition).ToList());
        }
예제 #9
0
        /// <nodoc />
        internal void FilterWorkspace(Workspace workspace, EvaluationFilter evaluationFilter)
        {
            if (!evaluationFilter.CanPerformPartialEvaluationScript(PrimaryConfigFile))
            {
                return;
            }

            using (var sw = Watch.Start())
            {
                int originalCount = workspace.SpecCount;

                // WorkspaceFilter updates the existing workspace instead of creating brand new one.
                // This is crucial to avoid redundant type checking required for semantic workspace creation.
                var filter = new WorkspaceFilter(FrontEndContext.PathTable);
                workspace.FilterWorkspace(filter.FilterForConversion(workspace, evaluationFilter));

                Logger.WorkspaceFiltered(LoggingContext, workspace.SpecCount, originalCount, sw.ElapsedMilliseconds);
            }
        }
예제 #10
0
        public IEnumerable <IFixtureSelector> Organize(FixtureLibrary library, WorkspaceFilter workspace)
        {
            var namespaces = new Cache <string, NamespaceSelector>(ns => new NamespaceSelector(ns));
            var fixtures   = new Cache <string, FixtureSelector>();

            // pass #1, collate the namespaces
            string[] names = getAllNamespaces(library, namespaces);

            var topLevels = collateNamespaces(namespaces, names);

            buildFixtureSelectors(library, namespaces, fixtures);

            selectFixtures(fixtures, workspace);
            selectNamespaces(namespaces, workspace);

            namespaces.Each(x => x.SetInitialState());

            return(topLevels.ToArray());
        }
예제 #11
0
        public void integrate_with_workspace_filter()
        {
            var workspace = new WorkspaceFilter();

            workspace.AddFilter(new FixtureFilter()
            {
                Name = typeof(MathFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            workspace.AddFilter(new FixtureFilter()
            {
                Name = typeof(AnotherFixture).GetFixtureAlias(),
                Type = FilterType.Fixture
            });

            var filter = workspace.CreateTypeFilter();

            filter.Matches(typeof(MathFixture)).ShouldBeTrue();

            filter.Matches(typeof(AnotherFixture)).ShouldBeTrue();

            filter.Matches(GetType()).ShouldBeFalse();
        }
예제 #12
0
        /// <summary>
        /// Tries to filter a given workspace definition by reusing information from the previous BuildXL invocation.
        /// </summary>
        /// <returns>
        /// 1. Failure if the error occurred during parsing/binding one of the changed specs.
        /// 2. Result(null) when the filtering failed due to symbols mismatch or due to another reason.
        /// 3. Result(WorkspaceDefinition) when the filtering succeeded.
        /// </returns>
        /// <remarks>
        /// If the previous binding information can be reused, then the set of specs that are safe to use as public facades + serialized AST
        /// are identified as well
        /// </remarks>
        private async Task <FilteredWorkspaceDefinition> TryFilterWorkspaceDefinitionIncrementallyAsync(
            List <string> changedFiles,
            IWorkspaceProvider workspaceProvider,
            WorkspaceDefinition workspaceDefinition,
            EvaluationFilter evaluationFilter)
        {
            Logger.TryingToReuseFrontEndSnapshot(LoggingContext);

            // TODO: potentially, we could check the number of changes compared to the workspace definition size.
            // If the number of changes is too big, maybe we should go into the full parse mode.
            // But we need to check the perf implications before making this decision.
            var changedSpecs = changedFiles.Select(
                p =>
            {
                var fullPath         = AbsolutePath.Create(FrontEndContext.PathTable, p);
                var containingModule = workspaceDefinition.TryGetModuleDefinition(fullPath);
                return(new SpecWithOwningModule(fullPath, containingModule));
            }).ToArray();

            // Need to check if the spec does not belong to the current workspace
            // or the changed spec belongs to the prelude.
            foreach (var changedSpec in changedSpecs)
            {
                if (changedSpec.OwningModule == null)
                {
                    Logger.FailToReuseFrontEndSnapshot(
                        LoggingContext,
                        I($"Changed spec file '{changedSpec.Path.ToString(FrontEndContext.PathTable)}' is not part of the computed workspace."));
                    return(FilteredWorkspaceDefinition.CanNotFilter());
                }

                if (changedSpec.OwningModule.Descriptor == workspaceDefinition.PreludeModule.Descriptor)
                {
                    Logger.FailToReuseFrontEndSnapshot(
                        LoggingContext,
                        I($"Changed spec file '{changedSpec.Path.ToString(FrontEndContext.PathTable)}' is part of the prelude."));
                    return(FilteredWorkspaceDefinition.CanNotFilter());
                }
            }

            // Getting the snapshot from the previous run.

            // Binding snapshot contains all the specs as well as all the configuration files.
            // Need to adjust the count.
            var expectedNumberOfSpecs = workspaceDefinition.SpecCount + (workspaceProvider.GetConfigurationModule()?.Specs.Count ?? 0);
            var snapshot = FrontEndArtifactManager.TryLoadFrontEndSnapshot(expectedNumberOfSpecs);

            if (snapshot == null)
            {
                // The error message was already logged.
                return(FilteredWorkspaceDefinition.CanNotFilter());
            }

            // Parsing and binding all the changed specs.
            var possibleParseResult = await workspaceProvider.ParseAndBindSpecsAsync(changedSpecs);

            var firstFailure = LogParseOrBindingErrorsIfAny(possibleParseResult);

            if (firstFailure != null)
            {
                // This is actual failure.
                // Instead of switching to the full mode, we can actually stop here.
                return(FilteredWorkspaceDefinition.Error(firstFailure));
            }

            // Snapshot is valid and parse/binding is completed successfully.
            var snapshotState = GetSnapshotReuseState(possibleParseResult, snapshot);

            if (snapshotState.State == SnapshotState.NoMatch)
            {
                // NoMatch is returned if the snapshot is unavailable.
                if (snapshotState.SpecsWithIncompatiblePublicSurface.Count != 0)
                {
                    Logger.FailToReuseFrontEndSnapshot(
                        LoggingContext,
                        I($"Spec file '{snapshotState.SpecsWithIncompatiblePublicSurface.First().Path.AbsolutePath}' changed its binding symbols."));
                }

                return(FilteredWorkspaceDefinition.CanNotFilter());
            }

            // Changed file could get different symbols.
            // Need to re-save it within the front-end snapshot.
            UpdateAndSaveSnapshot(possibleParseResult, snapshot);

            var snapshotProvider = new SnapshotBasedSpecProvider(snapshot);

            // Now we know exactly which are all the files that need to go through parsing/type checking/AST conversion. So we
            // inform that to the artifact manager so the public surface and AST serialization
            // can be resued for the rest, if available.
            // Observe these set of files are not reflecting a potential user filter, but that's fine. If there is a dirty spec
            // that is outside of the filter, that spec won't be requested by the workspace anyway
            NotifyDirtySpecsForPublicFacadeAndAstReuse(
                snapshotProvider,
                workspaceDefinition,
                changedSpecs.Select(f => f.Path).ToList());

            // The fingerprints for all changed specs are still the same,
            // so we can filter the workspace definition provided that the filter allows it.
            if (snapshotState.State == SnapshotState.FullMatch)
            {
                var filter            = new WorkspaceFilter(FrontEndContext.PathTable);
                var filteredWorkspace = evaluationFilter.CanPerformPartialEvaluationScript(PrimaryConfigFile)
                    ? filter.FilterWorkspaceDefinition(workspaceDefinition, evaluationFilter, snapshotProvider)
                    : workspaceDefinition.Modules;

                return(FilteredWorkspaceDefinition.Filter(new WorkspaceDefinition(filteredWorkspace, workspaceDefinition.PreludeModule)));
            }

            // Specs are not the same, but we would be able to load public facades for all unaffected specs.
            var dirtySpecNames = string.Join(
                ", ",
                snapshotState.SpecsWithTheSamePublicSurface.Take(10).Select(p => Path.GetFileName(p.Path.AbsolutePath)));

            Logger.FailedToFilterWorkspaceDefinition(
                LoggingContext,
                I($"{dirtySpecNames} changed one or more declarations."));

            return(FilteredWorkspaceDefinition.CanNotFilter());
        }
예제 #13
0
 public IEnumerable <IStartupActionSelector> GetActionSelectors(FixtureLibrary library, WorkspaceFilter filter)
 {
     return(library.StartupActions.Select(x => new StartupActionSelector(x, filter.StartupActions.Contains(x))).ToArray());
 }
예제 #14
0
 public FixtureAssembly(IProject project)
 {
     _systemTypeName = project.SystemTypeName;
     _fixtureAssembly = project.FixtureAssembly;
     _filter = project.CurrentFixtureFilter();
 }
예제 #15
0
 public FixtureAssembly(IProject project)
 {
     _systemTypeName  = project.SystemTypeName;
     _fixtureAssembly = project.FixtureAssembly;
     _filter          = project.CurrentFixtureFilter();
 }
예제 #16
0
 private void selectNamespaces(Cache <string, NamespaceSelector> namespaces, WorkspaceFilter workspace)
 {
     workspace.Filters.Where(x => x.Type == FilterType.Namespace).Each(x => namespaces[x.Name].Select(true));
 }
 private void selectNamespaces(Cache<string, NamespaceSelector> namespaces, WorkspaceFilter workspace)
 {
     workspace.Filters.Where(x => x.Type == FilterType.Namespace).Each(x => namespaces[x.Name].Select(true));
 }
 private void selectFixtures(Cache<string, FixtureSelector> fixtures, WorkspaceFilter workspace)
 {
     workspace.Filters
         .Where(x => x.Type == FilterType.Fixture)
         .Each(x => fixtures.WithValue(x.Name, selector => selector.Select(true)));
 }
예제 #19
0
 private void selectFixtures(Cache <string, FixtureSelector> fixtures, WorkspaceFilter workspace)
 {
     workspace.Filters
     .Where(x => x.Type == FilterType.Fixture)
     .Each(x => fixtures.WithValue(x.Name, selector => selector.Select(true)));
 }
예제 #20
0
        private void FilterWorkspace(Workspace workspace, EvaluationFilter filter)
        {
            var workspaceFilter = new WorkspaceFilter(m_pathTable);

            workspace.FilterWorkspace(workspaceFilter.FilterForConversion(workspace, filter));
        }
 public IEnumerable<IStartupActionSelector> GetActionSelectors(FixtureLibrary library, WorkspaceFilter filter)
 {
     return library.StartupActions.Select(x => new StartupActionSelector(x, filter.StartupActions.Contains(x))).ToArray();
 }