private ProjectGraphNode CreateNewNode( ConfigurationMetadata configurationMetadata, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory) { // TODO: ProjectInstance just converts the dictionary back to a PropertyDictionary, so find a way to directly provide it. var globalProperties = configurationMetadata.GlobalProperties.ToDictionary(); var projectInstance = projectInstanceFactory( configurationMetadata.ProjectFullPath, globalProperties, projectCollection); if (projectInstance == null) { throw new InvalidOperationException(ResourceUtilities.GetResourceString("NullReferenceFromProjectInstanceFactory")); } var graphNode = new ProjectGraphNode( projectInstance, globalProperties); _allParsedProjects[configurationMetadata] = graphNode; return(graphNode); }
public static ConfigurationMetadata ToModuleConfiguration(this Module module) { if (module == null) { throw new ArgumentNullException("module"); } var configuration = new ConfigurationMetadata { GroupName = module.Group.Name, Name = module.Name }; foreach (PropertyValue property in module.PropertyValues) { if (configuration.Properties.ContainsKey(property.Property.Name)) { throw new ConfigurationErrorsException( String.Format("Module [{0}] configuration property [{1}] is defined more than once.", configuration.Name, property.Property.Name)); } configuration.Properties[property.Property.Name] = property.Value; } return(configuration); }
private static List <ConfigurationMetadata> AddGraphBuildPropertyToEntryPoints(IEnumerable <ProjectGraphEntryPoint> entryPoints) { { var entryPointConfigurationMetadata = new List <ConfigurationMetadata>(); foreach (var entryPoint in entryPoints) { var globalPropertyDictionary = CreatePropertyDictionary(entryPoint.GlobalProperties); AddGraphBuildGlobalVariable(globalPropertyDictionary); var configurationMetadata = new ConfigurationMetadata(FileUtilities.NormalizePath(entryPoint.ProjectFile), globalPropertyDictionary); entryPointConfigurationMetadata.Add(configurationMetadata); } return(entryPointConfigurationMetadata); } void AddGraphBuildGlobalVariable(PropertyDictionary <ProjectPropertyInstance> globalPropertyDictionary) { if (globalPropertyDictionary.GetProperty(PropertyNames.IsGraphBuild) == null) { globalPropertyDictionary[PropertyNames.IsGraphBuild] = ProjectPropertyInstance.Create(PropertyNames.IsGraphBuild, "true"); } } }
public void TestValidConfiguration() { BuildRequestData data = new BuildRequestData("file", new Dictionary<string, string>(), "toolsVersion", new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, "2.0"); ConfigurationMetadata metadata = new ConfigurationMetadata(config); Assert.AreEqual(data.ProjectFullPath, metadata.ProjectFullPath); Assert.AreEqual(data.ExplicitlySpecifiedToolsVersion, metadata.ToolsVersion); }
public void TestConstructorNullConfiguration() { Assert.Throws <ArgumentNullException>(() => { BuildRequestConfiguration config = null; ConfigurationMetadata metadata = new ConfigurationMetadata(config); } ); }
public void TestConstructorNullProject() { Assert.Throws<ArgumentNullException>(() => { Project project = null; ConfigurationMetadata metadata = new ConfigurationMetadata(project); } ); }
public void TestConstructorNullConfiguration() { Assert.Throws<ArgumentNullException>(() => { BuildRequestConfiguration config = null; ConfigurationMetadata metadata = new ConfigurationMetadata(config); } ); }
public void TestConstructorNullProject() { Assert.Throws <ArgumentNullException>(() => { Project project = null; ConfigurationMetadata metadata = new ConfigurationMetadata(project); } ); }
public void TestValidConfiguration() { BuildRequestData data = new BuildRequestData("file", new Dictionary <string, string>(), "toolsVersion", new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, "2.0"); ConfigurationMetadata metadata = new ConfigurationMetadata(config); Assert.Equal(data.ProjectFullPath, metadata.ProjectFullPath); Assert.Equal(data.ExplicitlySpecifiedToolsVersion, metadata.ToolsVersion); }
public void TestValidProject() { Project project = CreateProject(); ConfigurationMetadata metadata = new ConfigurationMetadata(project); Assert.Equal(project.FullPath, metadata.ProjectFullPath); Assert.Equal(project.ToolsVersion, metadata.ToolsVersion); }
public IEnumerable <ReferenceInfo> GetReferences(ProjectInstance requesterInstance) { IEnumerable <ProjectItemInstance> projectReferenceItems; IEnumerable <GlobalPropertiesModifier> globalPropertiesModifiers = null; switch (GetProjectType(requesterInstance)) { case ProjectType.OuterBuild: projectReferenceItems = ConstructInnerBuildReferences(requesterInstance); break; case ProjectType.InnerBuild: globalPropertiesModifiers = ModifierForNonMultitargetingNodes.Add((parts, reference) => parts.AddPropertyToUndefine(GetInnerBuildPropertyName(requesterInstance))); projectReferenceItems = requesterInstance.GetItems(ItemTypeNames.ProjectReference); break; case ProjectType.NonMultitargeting: globalPropertiesModifiers = ModifierForNonMultitargetingNodes; projectReferenceItems = requesterInstance.GetItems(ItemTypeNames.ProjectReference); break; default: throw new ArgumentOutOfRangeException(); } foreach (var projectReferenceItem in projectReferenceItems) { if (!String.IsNullOrEmpty(projectReferenceItem.GetMetadataValue(ToolsVersionMetadataName))) { throw new InvalidOperationException( String.Format( CultureInfo.InvariantCulture, ResourceUtilities.GetResourceString( "ProjectGraphDoesNotSupportProjectReferenceWithToolset"), projectReferenceItem.EvaluatedInclude, requesterInstance.FullPath)); } var projectReferenceFullPath = projectReferenceItem.GetMetadataValue(FullPathMetadataName); var referenceGlobalProperties = GetGlobalPropertiesForItem(projectReferenceItem, requesterInstance.GlobalPropertiesDictionary, globalPropertiesModifiers); var requesterPlatform = ""; var requesterPlatformLookupTable = ""; if (ConversionUtilities.ValidBooleanTrue(requesterInstance.GetPropertyValue("EnableDynamicPlatformResolution"))) { requesterPlatform = requesterInstance.GetPropertyValue("Platform"); requesterPlatformLookupTable = requesterInstance.GetPropertyValue("PlatformLookupTable"); } var referenceConfig = new ConfigurationMetadata(projectReferenceFullPath, referenceGlobalProperties, requesterPlatform, requesterPlatformLookupTable, projectReferenceItem.HasMetadata("SetPlatform")); yield return(new ReferenceInfo(referenceConfig, projectReferenceItem)); } }
public void UpdateConfigMetaData(ConfigurationMetadata newMetaData) { if (newMetaData.GameMode != ConfigMetaData?.GameMode) { foreach (Action <GameModeId?> gameModeListener in gameModeListeners) { gameModeListener(newMetaData.GameMode); } } ConfigMetaData = newMetaData; }
/// <summary> /// Constructs a graph starting from the given graph entry points, evaluating with the provided project collection. /// </summary> /// <param name="entryPoints">The entry points to use in constructing the graph</param> /// <param name="projectCollection">The collection with which all projects in the graph should be associated. May not be null.</param> /// <param name="projectInstanceFactory"> /// A delegate used for constructing a <see cref="ProjectInstance"/>, called for each /// project created during graph creation. This value can be null, which uses /// a default implementation that calls the ProjectInstance constructor. See the remarks /// on <see cref="ProjectInstanceFactoryFunc"/> for other scenarios. /// </param> /// <exception cref="AggregateException">If the evaluation of any project in the graph fails, the InnerException contains <see cref="InvalidProjectFileException"/> /// If a null reference is returned from <paramref name="projectInstanceFactory"/>, the InnerException contains <see cref="InvalidOperationException"/></exception> /// <exception cref="CircularDependencyException">If the evaluation is successful but the project graph contains a circular dependency</exception> public ProjectGraph( IEnumerable <ProjectGraphEntryPoint> entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory) { ErrorUtilities.VerifyThrowArgumentNull(projectCollection, nameof(projectCollection)); projectInstanceFactory = projectInstanceFactory ?? DefaultProjectInstanceFactory; var nodeStates = new Dictionary <ProjectGraphNode, NodeState>(); var entryPointNodes = new List <ProjectGraphNode>(); var tasksInProgress = new ConcurrentDictionary <ConfigurationMetadata, object>(); var projectsToEvaluate = new ConcurrentQueue <ConfigurationMetadata>(); var entryPointConfigurationMetadata = new List <ConfigurationMetadata>(); foreach (var entryPoint in entryPoints) { PropertyDictionary <ProjectPropertyInstance> globalPropertyDictionary = CreatePropertyDictionary(entryPoint.GlobalProperties); var configurationMetadata = new ConfigurationMetadata(FileUtilities.NormalizePath(entryPoint.ProjectFile), globalPropertyDictionary); projectsToEvaluate.Enqueue(configurationMetadata); entryPointConfigurationMetadata.Add(configurationMetadata); } if (LoadGraph(projectsToEvaluate, projectCollection, tasksInProgress, projectInstanceFactory, out List <Exception> exceptions)) { foreach (var configurationMetadata in entryPointConfigurationMetadata) { entryPointNodes.Add(_allParsedProjects[configurationMetadata]); if (!nodeStates.TryGetValue(_allParsedProjects[configurationMetadata], out var _)) { DetectCycles(_allParsedProjects[configurationMetadata], nodeStates, projectCollection, configurationMetadata.GlobalProperties); } } var graphRoots = new List <ProjectGraphNode>(entryPointNodes.Count); foreach (var entryPointNode in entryPointNodes) { if (entryPointNode.ReferencingProjects.Count == 0) { graphRoots.Add(entryPointNode); } } EntryPointNodes = entryPointNodes.AsReadOnly(); ProjectNodes = _allParsedProjects.Values.ToList(); GraphRoots = graphRoots.AsReadOnly(); _projectNodesTopologicallySorted = new Lazy <IReadOnlyCollection <ProjectGraphNode> >(() => TopologicalSort(GraphRoots, ProjectNodes)); } else { throw new AggregateException(exceptions); } }
public void TestGetHashCode() { BuildRequestData data = new BuildRequestData("file", new Dictionary <string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); Project project = CreateProject(); ConfigurationMetadata metadata1 = new ConfigurationMetadata(config); ConfigurationMetadata metadata2 = new ConfigurationMetadata(project); Assert.Equal(metadata1.GetHashCode(), metadata2.GetHashCode()); }
public void EnsureCountIsNotRecursive() { // Given IConfiguration configuration = GetConfiguration(); ConfigurationMetadata metadata = new ConfigurationMetadata(configuration); // When int count = metadata.Count; // Then count.ShouldBe(14); }
public void ContainsKey(string key, bool expected) { // Given IConfiguration configuration = GetConfiguration(); ConfigurationMetadata metadata = new ConfigurationMetadata(configuration); // When bool result = metadata.ContainsKey(key); // Then result.ShouldBe(expected); }
public void GetsSimpleValue() { // Given IConfiguration configuration = GetConfiguration(); ConfigurationMetadata metadata = new ConfigurationMetadata(configuration); // When bool result = metadata.TryGetRaw("key0", out object value); // Then result.ShouldBeTrue(); value.ShouldBe("value0"); }
public BuildRequestConfiguration GetMatchingConfiguration(ConfigurationMetadata configMetadata) { var overrideConfig = _override.GetMatchingConfiguration(configMetadata); if (overrideConfig != null) { #if DEBUG ErrorUtilities.VerifyThrow(CurrentCache.GetMatchingConfiguration(configMetadata) == null, "caches should not overlap"); #endif return(overrideConfig); } else { return(CurrentCache.GetMatchingConfiguration(configMetadata)); } }
public void TestTranslation() { var globalProperties = new PropertyDictionary <ProjectPropertyInstance>(); globalProperties["a"] = ProjectPropertyInstance.Create("a", "b"); var initial = new ConfigurationMetadata("path", globalProperties); initial.Translate(TranslationHelpers.GetWriteTranslator()); var copy = ConfigurationMetadata.FactoryForDeserialization(TranslationHelpers.GetReadTranslator()); copy.ProjectFullPath.ShouldBe(initial.ProjectFullPath); copy.ToolsVersion.ShouldBe(initial.ToolsVersion); Assert.Equal(copy.GlobalProperties.GetCopyOnReadEnumerable(), initial.GlobalProperties.GetCopyOnReadEnumerable(), EqualityComparer <ProjectPropertyInstance> .Default); }
private ParsedProject ParseProject(ConfigurationMetadata configurationMetadata) { // TODO: ProjectInstance just converts the dictionary back to a PropertyDictionary, so find a way to directly provide it. var globalProperties = configurationMetadata.GlobalProperties.ToDictionary(); ProjectGraphNode graphNode; ProjectInstance projectInstance; var negotiatePlatform = PlatformNegotiationEnabled && !configurationMetadata.IsSetPlatformHardCoded; projectInstance = _projectInstanceFactory( configurationMetadata.ProjectFullPath, negotiatePlatform ? null : globalProperties, // Platform negotiation requires an evaluation with no global properties first _projectCollection); if (ConversionUtilities.ValidBooleanTrue(projectInstance.GetPropertyValue(EnableDynamicPlatformResolutionMetadataName))) { PlatformNegotiationEnabled = true; } if (projectInstance == null) { throw new InvalidOperationException(ResourceUtilities.GetResourceString("NullReferenceFromProjectInstanceFactory")); } if (negotiatePlatform) { var selectedPlatform = PlatformNegotiation.GetNearestPlatform(projectInstance.GetPropertyValue(PlatformMetadataName), projectInstance.GetPropertyValue(PlatformsMetadataName), projectInstance.GetPropertyValue(PlatformLookupTableMetadataName), configurationMetadata.PreviousPlatformLookupTable, projectInstance.FullPath, configurationMetadata.PreviousPlatform); if (selectedPlatform.Equals(String.Empty)) { globalProperties.Remove(PlatformMetadataName); } else { globalProperties[PlatformMetadataName] = selectedPlatform; } projectInstance = _projectInstanceFactory( configurationMetadata.ProjectFullPath, globalProperties, _projectCollection); } graphNode = new ProjectGraphNode(projectInstance); var referenceInfos = ParseReferences(graphNode); return(new ParsedProject(configurationMetadata, graphNode, referenceInfos)); }
public IEnumerable <ConfigurationMetadata> GetReferences(ProjectInstance requesterInstance) { IEnumerable <ProjectItemInstance> references; IEnumerable <GlobalPropertiesModifier> globalPropertiesModifiers = null; switch (GetProjectType(requesterInstance)) { case ProjectType.OuterBuild: references = GetInnerBuildReferences(requesterInstance); break; case ProjectType.InnerBuild: globalPropertiesModifiers = ModifierForNonMultitargetingNodes.Add((parts, reference) => parts.AddPropertyToUndefine(GetInnerBuildPropertyName(requesterInstance))); references = requesterInstance.GetItems(ItemTypeNames.ProjectReference); break; case ProjectType.NonMultitargeting: globalPropertiesModifiers = ModifierForNonMultitargetingNodes; references = requesterInstance.GetItems(ItemTypeNames.ProjectReference); break; default: throw new ArgumentOutOfRangeException(); } foreach (var projectReference in references) { if (!String.IsNullOrEmpty(projectReference.GetMetadataValue(ToolsVersionMetadataName))) { throw new InvalidOperationException( String.Format( CultureInfo.InvariantCulture, ResourceUtilities.GetResourceString( "ProjectGraphDoesNotSupportProjectReferenceWithToolset"), projectReference.EvaluatedInclude, requesterInstance.FullPath)); } var projectReferenceFullPath = projectReference.GetMetadataValue(FullPathMetadataName); var referenceGlobalProperties = GetGlobalPropertiesForItem(projectReference, requesterInstance.GlobalPropertiesDictionary, globalPropertiesModifiers); var referenceConfig = new ConfigurationMetadata(projectReferenceFullPath, referenceGlobalProperties); yield return(referenceConfig); } }
public void GetsSectionValue() { // Given IConfiguration configuration = GetConfiguration(); ConfigurationMetadata metadata = new ConfigurationMetadata(configuration); // When bool result = metadata.TryGetRaw("section0", out object value); object value2 = null; bool result2 = (value as ConfigurationMetadata)?.TryGetRaw("key1", out value2) ?? false; // Then result.ShouldBeTrue(); value.ShouldBeOfType <ConfigurationMetadata>(); result2.ShouldBeTrue(); value2.ShouldBe("value1"); }
public static ConfigurationMetadata ToModuleConfiguration(this Module module) { if (module == null) throw new ArgumentNullException("module"); var configuration = new ConfigurationMetadata {GroupName = module.Group.Name, Name = module.Name}; foreach (PropertyValue property in module.PropertyValues) { if (configuration.Properties.ContainsKey(property.Property.Name)) throw new ConfigurationErrorsException( String.Format("Module [{0}] configuration property [{1}] is defined more than once.", configuration.Name, property.Property.Name)); configuration.Properties[property.Property.Name] = property.Value; } return configuration; }
private ParsedProject ParseProject(ConfigurationMetadata configurationMetadata) { // TODO: ProjectInstance just converts the dictionary back to a PropertyDictionary, so find a way to directly provide it. var globalProperties = configurationMetadata.GlobalProperties.ToDictionary(); var projectInstance = _projectInstanceFactory( configurationMetadata.ProjectFullPath, globalProperties, _projectCollection); if (projectInstance == null) { throw new InvalidOperationException(ResourceUtilities.GetResourceString("NullReferenceFromProjectInstanceFactory")); } var graphNode = new ProjectGraphNode(projectInstance); var referenceInfos = ParseReferences(graphNode); return(new ParsedProject(configurationMetadata, graphNode, referenceInfos)); }
/// <summary> /// Constructs a graph starting from the given graph entry points, evaluating with the provided project collection. /// </summary> /// <param name="entryPoints">The entry points to use in constructing the graph</param> /// <param name="projectCollection">The collection with which all projects in the graph should be associated. May not be null.</param> /// <param name="projectInstanceFactory"> /// A delegate used for constructing a <see cref="ProjectInstance"/>, called for each /// project created during graph creation. This value can be null, which uses /// a default implementation that calls the ProjectInstance constructor. See the remarks /// on <see cref="ProjectInstanceFactoryFunc"/> for other scenarios. /// </param> /// <exception cref="AggregateException">If the evaluation of any project in the graph fails, the InnerException contains <see cref="InvalidProjectFileException"/> /// If a null reference is returned from <paramref name="projectInstanceFactory"/>, the InnerException contains <see cref="InvalidOperationException"/></exception> /// <exception cref="CircularDependencyException">If the evaluation is successful but the project graph contains a circular dependency</exception> public ProjectGraph( IEnumerable <ProjectGraphEntryPoint> entryPoints, ProjectCollection projectCollection, ProjectInstanceFactoryFunc projectInstanceFactory) { ErrorUtilities.VerifyThrowArgumentNull(projectCollection, nameof(projectCollection)); projectInstanceFactory = projectInstanceFactory ?? DefaultProjectInstanceFactory; _projectInterpretation = ProjectInterpretation.Instance; var entryPointConfigurationMetadata = new List <ConfigurationMetadata>(); foreach (var entryPoint in entryPoints) { var globalPropertyDictionary = CreatePropertyDictionary(entryPoint.GlobalProperties); AddGraphBuildGlobalVariable(globalPropertyDictionary); var configurationMetadata = new ConfigurationMetadata(FileUtilities.NormalizePath(entryPoint.ProjectFile), globalPropertyDictionary); entryPointConfigurationMetadata.Add(configurationMetadata); } var(entryPointNodes, rootNodes, allNodes) = LoadGraph(entryPointConfigurationMetadata, projectCollection, projectInstanceFactory, _projectInterpretation); EntryPointNodes = entryPointNodes; GraphRoots = rootNodes; ProjectNodes = allNodes; _projectNodesTopologicallySorted = new Lazy <IReadOnlyCollection <ProjectGraphNode> >(() => TopologicalSort(GraphRoots, ProjectNodes)); void AddGraphBuildGlobalVariable(PropertyDictionary <ProjectPropertyInstance> globalPropertyDictionary) { if (globalPropertyDictionary.GetProperty(PropertyNames.IsGraphBuild) == null) { globalPropertyDictionary[PropertyNames.IsGraphBuild] = ProjectPropertyInstance.Create(PropertyNames.IsGraphBuild, "true"); } } }
public void TestEquals() { BuildRequestData data = new BuildRequestData("file", new Dictionary <string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); Project project = CreateProject(); ConfigurationMetadata metadata1 = new ConfigurationMetadata(config); ConfigurationMetadata metadata2 = new ConfigurationMetadata(project); Assert.True(metadata1.Equals(metadata2)); data = new BuildRequestData("file2", new Dictionary <string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config2 = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); ConfigurationMetadata metadata3 = new ConfigurationMetadata(config2); Assert.False(metadata1.Equals(metadata3)); data = new BuildRequestData("file", new Dictionary <string, string>(), "3.0", new string[0], null); BuildRequestConfiguration config3 = new BuildRequestConfiguration(1, data, "3.0"); ConfigurationMetadata metadata4 = new ConfigurationMetadata(config3); Assert.False(metadata1.Equals(metadata4)); }
public void TestValidProject() { Project project = CreateProject(); ConfigurationMetadata metadata = new ConfigurationMetadata(project); Assert.AreEqual(project.FullPath, metadata.ProjectFullPath); Assert.AreEqual(project.ToolsVersion, metadata.ToolsVersion); }
private void ParseProject(ConfigurationMetadata projectToEvaluate) { _graphWorkSet.AddWork(projectToEvaluate, () => CreateNewNode(projectToEvaluate)); }
public void TestGetHashCode() { BuildRequestData data = new BuildRequestData("file", new Dictionary<string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); Project project = CreateProject(); ConfigurationMetadata metadata1 = new ConfigurationMetadata(config); ConfigurationMetadata metadata2 = new ConfigurationMetadata(project); Assert.AreEqual(metadata1.GetHashCode(), metadata2.GetHashCode()); }
public BuildRequestConfiguration GetMatchingConfiguration(ConfigurationMetadata configMetadata, ConfigCreateCallback callback, bool loadProject) { return(_override.GetMatchingConfiguration(configMetadata, callback, loadProject) ?? CurrentCache.GetMatchingConfiguration(configMetadata, callback, loadProject)); }
/// <remarks> /// Traverse an evaluated graph /// Maintain the state of each node (InProcess and Processed) to detect cycles /// returns false if loading the graph is not successful /// </remarks> private (bool success, List <string> projectsInCycle) DetectCycles(ProjectGraphNode node, Dictionary <ProjectGraphNode, NodeState> nodeState, ProjectCollection projectCollection, PropertyDictionary <ProjectPropertyInstance> globalProperties) { nodeState[node] = NodeState.InProcess; IEnumerable <ProjectItemInstance> projectReferenceItems = node.ProjectInstance.GetItems(MSBuildConstants.ProjectReferenceItemName); foreach (var projectReferenceToParse in projectReferenceItems) { string projectReferenceFullPath = projectReferenceToParse.GetMetadataValue(FullPathMetadataName); PropertyDictionary <ProjectPropertyInstance> projectReferenceGlobalProperties = GetProjectReferenceGlobalProperties(projectReferenceToParse, globalProperties); var projectReferenceConfigurationMetadata = new ConfigurationMetadata(projectReferenceFullPath, projectReferenceGlobalProperties); ProjectGraphNode projectReference = _allParsedProjects[projectReferenceConfigurationMetadata]; if (nodeState.TryGetValue(projectReference, out NodeState projectReferenceNodeState)) { // Because this is a depth-first search, we should only encounter new nodes or nodes whose subgraph has been completely processed. // If we encounter a node that is currently being processed(InProcess state), it must be one of the ancestors in a circular dependency. if (projectReferenceNodeState == NodeState.InProcess) { if (node.Equals(projectReference)) { // the project being evaluated has a reference to itself var selfReferencingProjectString = FormatCircularDependencyError(new List <string> { node.ProjectInstance.FullPath, node.ProjectInstance.FullPath }); throw new CircularDependencyException(string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), selfReferencingProjectString)); } else { // the project being evaluated has a circular dependency involving multiple projects // add this project to the list of projects involved in cycle var projectsInCycle = new List <string> { projectReferenceConfigurationMetadata.ProjectFullPath }; return(false, projectsInCycle); } } } else { // recursively process newly discovered references var loadReference = DetectCycles(projectReference, nodeState, projectCollection, projectReferenceGlobalProperties); if (!loadReference.success) { if (loadReference.projectsInCycle[0].Equals(node.ProjectInstance.FullPath)) { // we have reached the nth project in the cycle, form error message and throw loadReference.projectsInCycle.Add(projectReferenceConfigurationMetadata.ProjectFullPath); loadReference.projectsInCycle.Add(node.ProjectInstance.FullPath); var errorMessage = FormatCircularDependencyError(loadReference.projectsInCycle); throw new CircularDependencyException(string.Format( ResourceUtilities.GetResourceString("CircularDependencyInProjectGraph"), errorMessage)); } else { // this is one of the projects in the circular dependency // update the list of projects in cycle and return the list to the caller loadReference.projectsInCycle.Add(projectReferenceConfigurationMetadata.ProjectFullPath); return(false, loadReference.projectsInCycle); } } } ProjectGraphNode parsedProjectReference = _allParsedProjects[projectReferenceConfigurationMetadata]; node.AddProjectReference(parsedProjectReference); parsedProjectReference.AddReferencingProject(node); } nodeState[node] = NodeState.Processed; return(true, null); }
/// <summary> /// Load a graph with root node at entryProjectFile /// Maintain a queue of projects to be processed and evaluate projects in parallel /// Returns false if loading the graph is not successful /// </summary> private bool LoadGraph( ConcurrentQueue <ConfigurationMetadata> projectsToEvaluate, ProjectCollection projectCollection, ConcurrentDictionary <ConfigurationMetadata, object> tasksInProgress, ProjectInstanceFactoryFunc projectInstanceFactory, out List <Exception> exceptions) { var exceptionsInTasks = new ConcurrentBag <Exception>(); var evaluationWaitHandle = new AutoResetEvent(false); while (projectsToEvaluate.Count != 0 || tasksInProgress.Count != 0) { ConfigurationMetadata projectToEvaluate; if (projectsToEvaluate.Count != 0) { projectToEvaluate = projectsToEvaluate.Dequeue(); var task = new Task(() => { ProjectGraphNode parsedProject = CreateNewNode(projectToEvaluate, projectCollection, projectInstanceFactory); IEnumerable <ProjectItemInstance> projectReferenceItems = parsedProject.ProjectInstance.GetItems(MSBuildConstants.ProjectReferenceItemName); foreach (var projectReferenceToParse in projectReferenceItems) { if (!string.IsNullOrEmpty(projectReferenceToParse.GetMetadataValue(ToolsVersionMetadataName))) { throw new InvalidOperationException(string.Format( CultureInfo.InvariantCulture, ResourceUtilities.GetResourceString( "ProjectGraphDoesNotSupportProjectReferenceWithToolset"), projectReferenceToParse.EvaluatedInclude, parsedProject.ProjectInstance.FullPath)); } string projectReferenceFullPath = projectReferenceToParse.GetMetadataValue(FullPathMetadataName); PropertyDictionary <ProjectPropertyInstance> projectReferenceGlobalProperties = GetProjectReferenceGlobalProperties(projectReferenceToParse, projectToEvaluate.GlobalProperties); var projectReferenceConfigurationMetadata = new ConfigurationMetadata(projectReferenceFullPath, projectReferenceGlobalProperties); if (!tasksInProgress.ContainsKey(projectReferenceConfigurationMetadata)) { if (!_allParsedProjects.ContainsKey(projectReferenceConfigurationMetadata)) { projectsToEvaluate.Enqueue(projectReferenceConfigurationMetadata); evaluationWaitHandle.Set(); } } } }); if (tasksInProgress.TryAdd(projectToEvaluate, null)) { // once the task completes, remove it from tasksInProgress using a chained task // signal the wait handle to process new projects that have been discovered by this task or exit if all projects have been evaluated task.ContinueWith(_ => { if (task.IsFaulted) { exceptionsInTasks.Add(task.Exception.InnerException); } tasksInProgress.TryRemove(projectToEvaluate, out var _); evaluationWaitHandle.Set(); }); task.Start(); } } else { // if projectsToEvaluate is empty but there are tasks in progress, there is nothing to do till a task completes and discovers new projects // wait till a task completes and sends a signal evaluationWaitHandle.WaitOne(); } } if (exceptionsInTasks.Count != 0) { exceptions = exceptionsInTasks.ToList(); return(false); } exceptions = null; return(true); }
public void TestConstructorNullProject() { Project project = null; ConfigurationMetadata metadata = new ConfigurationMetadata(project); }
/// <summary> /// Gets a matching configuration. If no such configuration exists, one is created and optionally loaded. /// </summary> public BuildRequestConfiguration GetMatchingConfiguration(ConfigurationMetadata configMetadata, ConfigCreateCallback callback, bool loadProject) { lock (_configurations) { BuildRequestConfiguration configuration = GetMatchingConfiguration(configMetadata); // If there is no matching configuration, let the caller create one. if (configuration == null) { configuration = callback(null, loadProject); AddConfiguration(configuration); } else if (loadProject) { // We already had a configuration, load the project // If it exists but it cached, retrieve it if (configuration.IsCached) { configuration.RetrieveFromCache(); } // If it is still not loaded (because no instance was ever created here), let the caller populate the instance. if (!configuration.IsLoaded) { callback(configuration, loadProject: true); } } // In either case, make sure the project is loaded if it was requested. if (loadProject) { ErrorUtilities.VerifyThrow(configuration.IsLoaded, "Request to create configuration did not honor request to also load project."); } return configuration; } }
/// <summary> /// Returns the entry in the cache which matches the specified config. /// </summary> /// <param name="configMetadata">The configuration metadata to match</param> /// <returns>A matching configuration if one exists, null otherwise.</returns> public BuildRequestConfiguration GetMatchingConfiguration(ConfigurationMetadata configMetadata) { ErrorUtilities.VerifyThrowArgumentNull(configMetadata, "configMetadata"); lock (_configurations) { int configId; if (!_configurationIdsByMetadata.TryGetValue(configMetadata, out configId)) { return null; } return _configurations[configId]; } }
public ReferenceInfo(ConfigurationMetadata referenceConfiguration, ProjectItemInstance projectReferenceItem) { ReferenceConfiguration = referenceConfiguration; ProjectReferenceItem = projectReferenceItem; }
public void TestEquals() { BuildRequestData data = new BuildRequestData("file", new Dictionary<string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); Project project = CreateProject(); ConfigurationMetadata metadata1 = new ConfigurationMetadata(config); ConfigurationMetadata metadata2 = new ConfigurationMetadata(project); Assert.IsTrue(metadata1.Equals(metadata2)); data = new BuildRequestData("file2", new Dictionary<string, string>(), ObjectModelHelpers.MSBuildDefaultToolsVersion, new string[0], null); BuildRequestConfiguration config2 = new BuildRequestConfiguration(1, data, ObjectModelHelpers.MSBuildDefaultToolsVersion); ConfigurationMetadata metadata3 = new ConfigurationMetadata(config2); Assert.IsFalse(metadata1.Equals(metadata3)); data = new BuildRequestData("file", new Dictionary<string, string>(), "3.0", new string[0], null); BuildRequestConfiguration config3 = new BuildRequestConfiguration(1, data, "3.0"); ConfigurationMetadata metadata4 = new ConfigurationMetadata(config3); Assert.IsFalse(metadata1.Equals(metadata4)); }
public void TestConstructorNullConfiguration() { BuildRequestConfiguration config = null; ConfigurationMetadata metadata = new ConfigurationMetadata(config); }
private void SubmitProjectForParsing(ConfigurationMetadata projectToEvaluate) { _graphWorkSet.AddWork(projectToEvaluate, () => ParseProject(projectToEvaluate)); }