From 425abc4aff94a9cee5d3efc7e531c9f48257b920 Mon Sep 17 00:00:00 2001 From: Arun Kalyanasamy <arkalyan@microsoft.com> Date: Mon, 15 Mar 2021 11:30:48 -0700 Subject: [PATCH 1/2] Serializable project evaluation related changes --- ref/Microsoft.Build/net/Microsoft.Build.cs | 2 + .../netstandard/Microsoft.Build.cs | 2 + .../Instance/ProjectInstance_Tests.cs | 36 +++++ .../EvaluationLinkMocks/MockProjectLink.cs | 7 +- src/Build/Definition/Project.cs | 8 + src/Build/Instance/ProjectInstance.cs | 140 ++++++++++++------ .../DefinitionObjectsLinks/ProjectLink.cs | 5 + 7 files changed, 156 insertions(+), 44 deletions(-) diff --git a/ref/Microsoft.Build/net/Microsoft.Build.cs b/ref/Microsoft.Build/net/Microsoft.Build.cs index 147305e312c..808a0c01c6a 100644 --- a/ref/Microsoft.Build/net/Microsoft.Build.cs +++ b/ref/Microsoft.Build/net/Microsoft.Build.cs @@ -1126,6 +1126,7 @@ public partial class ProjectInstance public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml) { } public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, string subToolsetVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } + public ProjectInstance(Microsoft.Build.Evaluation.Project project, Microsoft.Build.Execution.ProjectInstanceSettings settings) { } public ProjectInstance(string projectFile) { } public ProjectInstance(string projectFile, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion) { } public ProjectInstance(string projectFile, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } @@ -1982,6 +1983,7 @@ protected ProjectLink() { } public abstract bool Build(string[] targets, System.Collections.Generic.IEnumerable<Microsoft.Build.Framework.ILogger> loggers, System.Collections.Generic.IEnumerable<Microsoft.Build.Logging.ForwardingLoggerRecord> remoteLoggers, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract Microsoft.Build.Execution.ProjectInstance CreateProjectInstance(Microsoft.Build.Execution.ProjectInstanceSettings settings, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract string ExpandString(string unexpandedValue); + public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(string itemType, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.ProvenanceResult> GetItemProvenance(Microsoft.Build.Evaluation.ProjectItem item, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); diff --git a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs index 395d69a8f6e..6707dd41599 100644 --- a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs +++ b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs @@ -1120,6 +1120,7 @@ public partial class ProjectInstance public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml) { } public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } public ProjectInstance(Microsoft.Build.Construction.ProjectRootElement xml, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, string subToolsetVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } + public ProjectInstance(Microsoft.Build.Evaluation.Project project, Microsoft.Build.Execution.ProjectInstanceSettings settings) { } public ProjectInstance(string projectFile) { } public ProjectInstance(string projectFile, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion) { } public ProjectInstance(string projectFile, System.Collections.Generic.IDictionary<string, string> globalProperties, string toolsVersion, Microsoft.Build.Evaluation.ProjectCollection projectCollection) { } @@ -1976,6 +1977,7 @@ protected ProjectLink() { } public abstract bool Build(string[] targets, System.Collections.Generic.IEnumerable<Microsoft.Build.Framework.ILogger> loggers, System.Collections.Generic.IEnumerable<Microsoft.Build.Logging.ForwardingLoggerRecord> remoteLoggers, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract Microsoft.Build.Execution.ProjectInstance CreateProjectInstance(Microsoft.Build.Execution.ProjectInstanceSettings settings, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract string ExpandString(string unexpandedValue); + public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.GlobResult> GetAllGlobs(string itemType, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); public abstract System.Collections.Generic.List<Microsoft.Build.Evaluation.ProvenanceResult> GetItemProvenance(Microsoft.Build.Evaluation.ProjectItem item, Microsoft.Build.Evaluation.Context.EvaluationContext evaluationContext); diff --git a/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs b/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs index d032033dd27..87c0d0a9c76 100644 --- a/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs +++ b/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs @@ -449,6 +449,42 @@ public void CreateProjectInstanceWithItemsContainingProjects() Assert.Equal(projAInstanceItem.MetadataCount, projAInstanceItem.MetadataNames.Count); } + /// <summary> + /// Constructs a new ProjectInstances from Project. + /// </summary> + [Fact] + public void CreateProjectInstanceFromProject() + { + const string CapturedMetadataName = "DefiningProjectFullPath"; + var pc = new ProjectCollection(); + var projA = ProjectRootElement.Create(pc); + var projB = ProjectRootElement.Create(pc); + projA.FullPath = Path.Combine(Path.GetTempPath(), "a.proj"); + projB.FullPath = Path.Combine(Path.GetTempPath(), "b.proj"); + projB.AddImport("a.proj"); + projA.AddItem("Compile", "aItem.cs"); + projB.AddItem("Compile", "bItem.cs"); + + var projBEval = new Project(projB, null, null, pc); + var projBInstance = new ProjectInstance(projBEval, ProjectInstanceSettings.ImmutableWithFastItemLookup); + var projBInstanceItem = projBInstance.GetItemsByItemTypeAndEvaluatedInclude("Compile", "bItem.cs").Single(); + var projAInstanceItem = projBInstance.GetItemsByItemTypeAndEvaluatedInclude("Compile", "aItem.cs").Single(); + Assert.Equal(projB.FullPath, projBInstanceItem.GetMetadataValue(CapturedMetadataName)); + Assert.Equal(projA.FullPath, projAInstanceItem.GetMetadataValue(CapturedMetadataName)); + + // Although GetMetadataValue returns non-null, GetMetadata returns null... + Assert.Null(projAInstanceItem.GetMetadata(CapturedMetadataName)); + + // .. Just like built-in metadata does: (this segment just demonstrates similar functionality -- it's not meant to test built-in metadata) + Assert.NotNull(projAInstanceItem.GetMetadataValue("Identity")); + Assert.Null(projAInstanceItem.GetMetadata("Identity")); + + Assert.True(projAInstanceItem.HasMetadata(CapturedMetadataName)); + Assert.False(projAInstanceItem.Metadata.Any()); + Assert.Contains(CapturedMetadataName, projAInstanceItem.MetadataNames); + Assert.Equal(projAInstanceItem.MetadataCount, projAInstanceItem.MetadataNames.Count); + } + /// <summary> /// Verifies that the built-in metadata for specialized ProjectInstances is present when items are based on wildcards in the construction model. /// </summary> diff --git a/src/Build.OM.UnitTests/ObjectModelRemoting/RemoteProjectsProviderMock/EvaluationLinkMocks/MockProjectLink.cs b/src/Build.OM.UnitTests/ObjectModelRemoting/RemoteProjectsProviderMock/EvaluationLinkMocks/MockProjectLink.cs index 253ceac7972..d268d30df18 100644 --- a/src/Build.OM.UnitTests/ObjectModelRemoting/RemoteProjectsProviderMock/EvaluationLinkMocks/MockProjectLink.cs +++ b/src/Build.OM.UnitTests/ObjectModelRemoting/RemoteProjectsProviderMock/EvaluationLinkMocks/MockProjectLink.cs @@ -187,7 +187,12 @@ public override bool Build(string[] targets, IEnumerable<ILogger> loggers, IEnum public override string ExpandString(string unexpandedValue) => this.Proxy.ExpandString(unexpandedValue); -// TODO: Glob is not needed for the CSproj, but we might want to test it at least + // TODO: Glob is not needed for the CSproj, but we might want to test it at least + public override List<GlobResult> GetAllGlobs() + { + throw new NotImplementedException(); + } + public override List<GlobResult> GetAllGlobs(EvaluationContext evaluationContext) { throw new NotImplementedException(); diff --git a/src/Build/Definition/Project.cs b/src/Build/Definition/Project.cs index 285c4cc592a..014f8e68993 100644 --- a/src/Build/Definition/Project.cs +++ b/src/Build/Definition/Project.cs @@ -2421,6 +2421,14 @@ public override bool IsBuildEnabled /// </summary> internal ILoggingService LoggingService => ProjectCollection.LoggingService; + /// <summary> + /// See <see cref="ProjectLink.GetAllGlobs()"/>. + /// </summary> + public override List<GlobResult> GetAllGlobs() + { + return GetAllGlobs(evaluationContext: null); + } + /// <summary> /// See <see cref="ProjectLink.GetAllGlobs(EvaluationContext)"/>. /// </summary> diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs index bd160b2f66c..44c900e26d7 100644 --- a/src/Build/Instance/ProjectInstance.cs +++ b/src/Build/Instance/ProjectInstance.cs @@ -326,6 +326,59 @@ public ProjectInstance(ProjectRootElement xml, IDictionary<string, string> globa { } + /// <summary> + /// Creates a ProjectInstance from an external created <see cref="Project"/>. + /// Properties and items are cloned immediately and only the instance data is stored. + /// </summary> + public ProjectInstance(Project project, ProjectInstanceSettings settings) + { + ErrorUtilities.VerifyThrowInternalNull(project, nameof(project)); + + var projectPath = project.FullPath; + _directory = Path.GetDirectoryName(projectPath); + _projectFileLocation = ElementLocation.Create(projectPath); + _hostServices = project.ProjectCollection.HostServices; + + EvaluationId = project.EvaluationCounter; + + var immutable = (settings & ProjectInstanceSettings.Immutable) == ProjectInstanceSettings.Immutable; + this.CreatePropertiesSnapshot(project.Properties, immutable); + this.CreateItemDefinitionsSnapshot(project.ItemDefinitions); + + var keepEvaluationCache = (settings & ProjectInstanceSettings.ImmutableWithFastItemLookup) == ProjectInstanceSettings.ImmutableWithFastItemLookup; + var projectItemToInstanceMap = this.CreateItemsSnapshot(project.Items, project.ItemTypes.Count, keepEvaluationCache); + + this.CreateEvaluatedIncludeSnapshotIfRequested(keepEvaluationCache, project.Items, projectItemToInstanceMap); + + _globalProperties = new PropertyDictionary<ProjectPropertyInstance>(project.GlobalProperties.Count); + foreach (var property in project.GlobalProperties) + { + _globalProperties.Set(ProjectPropertyInstance.Create(property.Key, property.Value)); + } + + this.CreateEnvironmentVariablePropertiesSnapshot(project.ProjectCollection.EnvironmentProperties); + this.CreateTargetsSnapshot(project.Targets, null, null, null, null); + this.CreateImportsSnapshot(project.Imports, project.ImportsIncludingDuplicates); + + this.Toolset = project.ProjectCollection.GetToolset(project.ToolsVersion); + this.SubToolsetVersion = project.SubToolsetVersion; + this.TaskRegistry = new TaskRegistry(Toolset, project.ProjectCollection.ProjectRootElementCache); + + this.ProjectRootElementCache = project.ProjectCollection.ProjectRootElementCache; + + this.EvaluatedItemElements = new List<ProjectItemElement>(project.Items.Count); + foreach (var item in project.Items) + { + this.EvaluatedItemElements.Add(item.Xml); + } + + _usingDifferentToolsVersionFromProjectFile = false; + _originalProjectToolsVersion = project.ToolsVersion; + _explicitToolsVersionSpecified = project.SubToolsetVersion != null; + + _isImmutable = immutable; + } + /// <summary> /// Creates a ProjectInstance directly. /// No intermediate Project object is created. @@ -461,18 +514,18 @@ internal ProjectInstance(Evaluation.Project.Data data, string directory, string EvaluationId = data.EvaluationId; var immutable = (settings & ProjectInstanceSettings.Immutable) == ProjectInstanceSettings.Immutable; - this.CreatePropertiesSnapshot(data, immutable); + this.CreatePropertiesSnapshot(new ReadOnlyCollection<ProjectProperty>(data.Properties), immutable); - this.CreateItemDefinitionsSnapshot(data); + this.CreateItemDefinitionsSnapshot(data.ItemDefinitions); var keepEvaluationCache = (settings & ProjectInstanceSettings.ImmutableWithFastItemLookup) == ProjectInstanceSettings.ImmutableWithFastItemLookup; - var projectItemToInstanceMap = this.CreateItemsSnapshot(data, keepEvaluationCache); + var projectItemToInstanceMap = this.CreateItemsSnapshot(new ReadOnlyCollection<ProjectItem>(data.Items), data.ItemTypes.Count, keepEvaluationCache); - this.CreateEvaluatedIncludeSnapshotIfRequested(keepEvaluationCache, data, projectItemToInstanceMap); - this.CreateGlobalPropertiesSnapshot(data); + this.CreateEvaluatedIncludeSnapshotIfRequested(keepEvaluationCache, new ReadOnlyCollection<ProjectItem>(data.Items), projectItemToInstanceMap); + this.CreateGlobalPropertiesSnapshot(data.GlobalPropertiesDictionary); this.CreateEnvironmentVariablePropertiesSnapshot(environmentVariableProperties); - this.CreateTargetsSnapshot(data); - this.CreateImportsSnapshot(data); + this.CreateTargetsSnapshot(data.Targets, data.DefaultTargets, data.InitialTargets, data.BeforeTargets, data.AfterTargets); + this.CreateImportsSnapshot(data.ImportClosure, data.ImportClosureWithDuplicates); this.Toolset = data.Toolset; // UNDONE: This isn't immutable, should be cloned or made immutable; it currently has a pointer to project collection this.SubToolsetVersion = data.SubToolsetVersion; @@ -548,13 +601,13 @@ private ProjectInstance(ProjectInstance that, bool isImmutable, RequestedProject this.DefaultTargets = new List<string>(that.DefaultTargets); this.InitialTargets = new List<string>(that.InitialTargets); ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, - ProjectItemDefinitionInstance>) this).BeforeTargets = CreateCloneDictionary( + ProjectItemDefinitionInstance>)this).BeforeTargets = CreateCloneDictionary( ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, - ProjectItemDefinitionInstance>) that).BeforeTargets, StringComparer.OrdinalIgnoreCase); + ProjectItemDefinitionInstance>)that).BeforeTargets, StringComparer.OrdinalIgnoreCase); ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, - ProjectItemDefinitionInstance>) this).AfterTargets = CreateCloneDictionary( + ProjectItemDefinitionInstance>)this).AfterTargets = CreateCloneDictionary( ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, - ProjectItemDefinitionInstance>) that).AfterTargets, StringComparer.OrdinalIgnoreCase); + ProjectItemDefinitionInstance>)that).AfterTargets, StringComparer.OrdinalIgnoreCase); this.TaskRegistry = that.TaskRegistry; // UNDONE: This isn't immutable, should be cloned or made immutable; it currently has a pointer to project collection @@ -2023,7 +2076,7 @@ private void TranslateProperties(ITranslator translator) translator.TranslateDictionary(ref _globalProperties, ProjectPropertyInstance.FactoryForDeserialization); translator.TranslateDictionary(ref _properties, ProjectPropertyInstance.FactoryForDeserialization); - var globalPropertiesToTreatAsLocal = (HashSet<string>) _globalPropertiesToTreatAsLocal; + var globalPropertiesToTreatAsLocal = (HashSet<string>)_globalPropertiesToTreatAsLocal; translator.Translate(ref globalPropertiesToTreatAsLocal); if (translator.Mode == TranslationDirection.ReadFromStream) @@ -2727,24 +2780,29 @@ private IEnumerable<ProjectItemInstance> GetItemsByEvaluatedInclude(string evalu /// <summary> /// Create various target snapshots /// </summary> - private void CreateTargetsSnapshot(Evaluation.Project.Data data) + private void CreateTargetsSnapshot( + IDictionary<string, ProjectTargetInstance> targets, + List<string> defaultTargets, + List<string> initialTargets, + IDictionary<string, List<TargetSpecification>> beforeTargets, + IDictionary<string, List<TargetSpecification>> afterTargets) { - this.DefaultTargets = new List<string>(data.DefaultTargets); - this.InitialTargets = new List<string>(data.InitialTargets); - ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).BeforeTargets = CreateCloneDictionary(data.BeforeTargets, StringComparer.OrdinalIgnoreCase); - ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).AfterTargets = CreateCloneDictionary(data.AfterTargets, StringComparer.OrdinalIgnoreCase); - // ProjectTargetInstances are immutable so only the dictionary must be cloned - _targets = CreateCloneDictionary(data.Targets); + _targets = CreateCloneDictionary(targets); + + this.DefaultTargets = new List<string>(defaultTargets); + this.InitialTargets = new List<string>(initialTargets); + ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).BeforeTargets = CreateCloneDictionary(beforeTargets, StringComparer.OrdinalIgnoreCase); + ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).AfterTargets = CreateCloneDictionary(afterTargets, StringComparer.OrdinalIgnoreCase); } /// <summary> /// Create various imports snapshots /// </summary> - private void CreateImportsSnapshot(Evaluation.Project.Data data) + private void CreateImportsSnapshot(IList<ResolvedImport> importClosure, IList<ResolvedImport> importClosureWithDuplicates) { - _importPaths = new List<string>(data.ImportClosure.Count - 1 /* outer project */); - foreach (var resolvedImport in data.ImportClosure) + _importPaths = new List<string>(importClosure.Count - 1 /* outer project */); + foreach (var resolvedImport in importClosure) { // Exclude outer project itself if (resolvedImport.ImportingElement != null) @@ -2755,8 +2813,8 @@ private void CreateImportsSnapshot(Evaluation.Project.Data data) ImportPaths = _importPaths.AsReadOnly(); - _importPathsIncludingDuplicates = new List<string>(data.ImportClosureWithDuplicates.Count - 1 /* outer project */); - foreach (var resolvedImport in data.ImportClosureWithDuplicates) + _importPathsIncludingDuplicates = new List<string>(importClosureWithDuplicates.Count - 1 /* outer project */); + foreach (var resolvedImport in importClosureWithDuplicates) { // Exclude outer project itself if (resolvedImport.ImportingElement != null) @@ -2784,11 +2842,11 @@ private void CreateEnvironmentVariablePropertiesSnapshot(PropertyDictionary<Proj /// <summary> /// Create global properties snapshot /// </summary> - private void CreateGlobalPropertiesSnapshot(Evaluation.Project.Data data) + private void CreateGlobalPropertiesSnapshot(PropertyDictionary<ProjectPropertyInstance> globalPropertiesDictionary) { - _globalProperties = new PropertyDictionary<ProjectPropertyInstance>(data.GlobalPropertiesDictionary.Count); + _globalProperties = new PropertyDictionary<ProjectPropertyInstance>(globalPropertiesDictionary.Count); - foreach (ProjectPropertyInstance globalProperty in data.GlobalPropertiesDictionary) + foreach (ProjectPropertyInstance globalProperty in globalPropertiesDictionary) { _globalProperties.Set(globalProperty.DeepClone()); } @@ -2797,7 +2855,7 @@ private void CreateGlobalPropertiesSnapshot(Evaluation.Project.Data data) /// <summary> /// Create evaluated include cache snapshot /// </summary> - private void CreateEvaluatedIncludeSnapshotIfRequested(bool keepEvaluationCache, Evaluation.Project.Data data, Dictionary<ProjectItem, ProjectItemInstance> projectItemToInstanceMap) + private void CreateEvaluatedIncludeSnapshotIfRequested(bool keepEvaluationCache, ICollection<ProjectItem> items, Dictionary<ProjectItem, ProjectItemInstance> projectItemToInstanceMap) { if (!keepEvaluationCache) { @@ -2805,26 +2863,22 @@ private void CreateEvaluatedIncludeSnapshotIfRequested(bool keepEvaluationCache, } _itemsByEvaluatedInclude = new MultiDictionary<string, ProjectItemInstance>(StringComparer.OrdinalIgnoreCase); - foreach (var key in data.ItemsByEvaluatedIncludeCache.Keys) + foreach (var item in items) { - var projectItems = data.ItemsByEvaluatedIncludeCache[key]; - foreach (var projectItem in projectItems) - { - _itemsByEvaluatedInclude.Add(key, projectItemToInstanceMap[projectItem]); - } + _itemsByEvaluatedInclude.Add(item.EvaluatedInclude, projectItemToInstanceMap[item]); } } /// <summary> /// Create Items snapshot /// </summary> - private Dictionary<ProjectItem, ProjectItemInstance> CreateItemsSnapshot(Evaluation.Project.Data data, bool keepEvaluationCache) + private Dictionary<ProjectItem, ProjectItemInstance> CreateItemsSnapshot(ICollection<ProjectItem> items, int itemTypecount, bool keepEvaluationCache) { - _items = new ItemDictionary<ProjectItemInstance>(data.ItemTypes.Count); + _items = new ItemDictionary<ProjectItemInstance>(itemTypecount); - var projectItemToInstanceMap = keepEvaluationCache ? new Dictionary<ProjectItem, ProjectItemInstance>(data.Items.Count) : null; + var projectItemToInstanceMap = keepEvaluationCache ? new Dictionary<ProjectItem, ProjectItemInstance>(items.Count) : null; - foreach (ProjectItem item in data.Items) + foreach (ProjectItem item in items) { List<ProjectItemDefinitionInstance> inheritedItemDefinitions = null; @@ -2865,11 +2919,11 @@ private Dictionary<ProjectItem, ProjectItemInstance> CreateItemsSnapshot(Evaluat /// <summary> /// Create ItemDefinitions snapshot /// </summary> - private void CreateItemDefinitionsSnapshot(Evaluation.Project.Data data) + private void CreateItemDefinitionsSnapshot(IDictionary<string, ProjectItemDefinition> itemDefinitions) { _itemDefinitions = new RetrievableEntryHashSet<ProjectItemDefinitionInstance>(MSBuildNameIgnoreCaseComparer.Default); - foreach (ProjectItemDefinition definition in data.ItemDefinitions.Values) + foreach (ProjectItemDefinition definition in itemDefinitions.Values) { _itemDefinitions.Add(new ProjectItemDefinitionInstance(definition)); } @@ -2878,11 +2932,11 @@ private void CreateItemDefinitionsSnapshot(Evaluation.Project.Data data) /// <summary> /// create property snapshot /// </summary> - private void CreatePropertiesSnapshot(Evaluation.Project.Data data, bool isImmutable) + private void CreatePropertiesSnapshot(ICollection<ProjectProperty> properties, bool isImmutable) { - _properties = new PropertyDictionary<ProjectPropertyInstance>(data.Properties.Count); + _properties = new PropertyDictionary<ProjectPropertyInstance>(properties.Count); - foreach (ProjectProperty property in data.Properties) + foreach (ProjectProperty property in properties) { // Allow reserved property names, since this is how they are added to the project instance. // The caller has prevented users setting them themselves. diff --git a/src/Build/ObjectModelRemoting/DefinitionObjectsLinks/ProjectLink.cs b/src/Build/ObjectModelRemoting/DefinitionObjectsLinks/ProjectLink.cs index c89d4ee4323..77fe8e0fcda 100644 --- a/src/Build/ObjectModelRemoting/DefinitionObjectsLinks/ProjectLink.cs +++ b/src/Build/ObjectModelRemoting/DefinitionObjectsLinks/ProjectLink.cs @@ -128,6 +128,11 @@ public abstract class ProjectLink /// </summary> public abstract int LastEvaluationId { get; } + /// <summary> + /// Facilitate remoting the <see cref="Project.GetAllGlobs()"/>. + /// </summary> + public abstract List<GlobResult> GetAllGlobs(); + /// <summary> /// Facilitate remoting the <see cref="Project.GetAllGlobs(EvaluationContext)"/>. /// </summary> From c832a2a32844bca8e77cc7c919575975028ef60f Mon Sep 17 00:00:00 2001 From: Arun Kalyanasamy <arkalyan@microsoft.com> Date: Mon, 15 Mar 2021 16:47:01 -0700 Subject: [PATCH 2/2] Fix up test load settings --- src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs | 8 +++++++- src/Build/Instance/ProjectInstance.cs | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs b/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs index 87c0d0a9c76..dc1e3cfdc23 100644 --- a/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs +++ b/src/Build.OM.UnitTests/Instance/ProjectInstance_Tests.cs @@ -465,7 +465,13 @@ public void CreateProjectInstanceFromProject() projA.AddItem("Compile", "aItem.cs"); projB.AddItem("Compile", "bItem.cs"); - var projBEval = new Project(projB, null, null, pc); + var loadSettings = ProjectLoadSettings.RecordDuplicateButNotCircularImports + | ProjectLoadSettings.RejectCircularImports + | ProjectLoadSettings.IgnoreEmptyImports + | ProjectLoadSettings.IgnoreMissingImports + | ProjectLoadSettings.IgnoreInvalidImports; + + var projBEval = new Project(projB, null, null, pc, loadSettings); var projBInstance = new ProjectInstance(projBEval, ProjectInstanceSettings.ImmutableWithFastItemLookup); var projBInstanceItem = projBInstance.GetItemsByItemTypeAndEvaluatedInclude("Compile", "bItem.cs").Single(); var projAInstanceItem = projBInstance.GetItemsByItemTypeAndEvaluatedInclude("Compile", "aItem.cs").Single(); diff --git a/src/Build/Instance/ProjectInstance.cs b/src/Build/Instance/ProjectInstance.cs index 44c900e26d7..632b057bd4f 100644 --- a/src/Build/Instance/ProjectInstance.cs +++ b/src/Build/Instance/ProjectInstance.cs @@ -2790,8 +2790,8 @@ private void CreateTargetsSnapshot( // ProjectTargetInstances are immutable so only the dictionary must be cloned _targets = CreateCloneDictionary(targets); - this.DefaultTargets = new List<string>(defaultTargets); - this.InitialTargets = new List<string>(initialTargets); + this.DefaultTargets = defaultTargets == null ? new List<string>(0) : new List<string>(defaultTargets); + this.InitialTargets = defaultTargets == null ? new List<string>(0) : new List<string>(initialTargets); ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).BeforeTargets = CreateCloneDictionary(beforeTargets, StringComparer.OrdinalIgnoreCase); ((IEvaluatorData<ProjectPropertyInstance, ProjectItemInstance, ProjectMetadataInstance, ProjectItemDefinitionInstance>)this).AfterTargets = CreateCloneDictionary(afterTargets, StringComparer.OrdinalIgnoreCase); }