This commit is contained in:
Rainer Sigwald 2023-07-12 16:39:06 -05:00
Родитель 1b0ed759ab 971bf70db7
Коммит 2f8fe45756
34 изменённых файлов: 456 добавлений и 162 удалений

Просмотреть файл

@ -1 +1,2 @@
M:System.Globalization.CompareInfo.IndexOf(System.String,System.Char);CompareInfo.IndexOf can unexpectedly allocate strings--use string.IndexOf
P:Microsoft.Build.Construction.ProjectElementContainer.Children;Use ChildrenEnumerable instead to avoid boxing

Просмотреть файл

@ -28,7 +28,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Null(project.Imports.GetEnumerator().Current);
Assert.Empty(project.Imports);
}
/// <summary>

Просмотреть файл

@ -143,7 +143,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Null(project.Imports.GetEnumerator().Current);
Assert.Empty(project.Imports);
}
/// <summary>
@ -162,7 +162,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
ProjectImportGroupElement importGroup = (ProjectImportGroupElement)Helpers.GetFirst(project.ImportGroups);
Assert.Null(project.Imports.GetEnumerator().Current);
Assert.Empty(project.Imports);
Assert.Equal(0, Helpers.Count(importGroup.Imports));
}

Просмотреть файл

@ -24,7 +24,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Equal(0, Helpers.Count(project.Children));
Assert.Null(project.ItemDefinitionGroups.GetEnumerator().Current);
Assert.Empty(project.ItemDefinitionGroups);
}
/// <summary>

Просмотреть файл

@ -24,7 +24,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Equal(0, Helpers.Count(project.Children));
Assert.Null(project.ItemGroups.GetEnumerator().Current);
Assert.Empty(project.ItemGroups);
}
/// <summary>

Просмотреть файл

@ -23,7 +23,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Equal(0, Helpers.Count(project.Children));
Assert.Null(project.PropertyGroups.GetEnumerator().Current);
Assert.Empty(project.PropertyGroups);
}
/// <summary>

Просмотреть файл

@ -41,7 +41,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
public void ReadNoTarget()
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Null(project.Targets.GetEnumerator().Current);
Assert.Empty(project.Targets);
}
/// <summary>

Просмотреть файл

@ -25,7 +25,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
{
ProjectRootElement project = ProjectRootElement.Create();
Assert.Null(project.UsingTasks.GetEnumerator().Current);
Assert.Empty(project.UsingTasks);
}
/// <summary>

Просмотреть файл

@ -65,7 +65,7 @@ namespace Microsoft.Build.UnitTests.OM.Construction
UsingTaskParameterGroupElement parameterGroup = GetParameterGroupXml(s_contentEmptyParameterGroup);
Assert.NotNull(parameterGroup);
Assert.Equal(0, parameterGroup.Count);
Assert.Null(parameterGroup.Parameters.GetEnumerator().Current);
Assert.Empty(parameterGroup.Parameters);
}
/// <summary>

Просмотреть файл

@ -27,7 +27,7 @@ namespace Microsoft.Build.Graph.UnitTests
/// <summary>
/// Performs SetPlatform negotiation for all project references when opted
/// in via the EnableDynamicPlatformResolution property.
///
///
/// The static graph mirrors the negotiation during build to determine plartform for each node.
/// These tests mirror GetCompatiblePlatform_Tests.cs in order to make sure they both are in sync.
/// </summary>
@ -351,5 +351,102 @@ namespace Microsoft.Build.Graph.UnitTests
GetFirstNodeWithProjectNumber(graph, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe(GetFirstNodeWithProjectNumber(graph, 1).ProjectInstance.GetPropertyValue("Platform"));
}
}
// Validate configurations are defined in project reference protocol
[Fact]
public void SolutionWithoutAllConfigurations()
{
using (TestEnvironment testEnvironment = TestEnvironment.Create())
{
var firstProjectName = "1";
var secondProjectName = "2";
var thirdProjectName = "3";
TransientTestFolder folder = testEnvironment.CreateFolder(createFolder: true);
TransientTestFolder project1Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, firstProjectName), createFolder: true);
TransientTestFolder project1SubFolder = testEnvironment.CreateFolder(Path.Combine(project1Folder.Path, firstProjectName), createFolder: true);
TransientTestFile project1 = testEnvironment.CreateFile(project1SubFolder, $"{firstProjectName}.csproj",
@"<Project>
<PropertyGroup>
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
<Platform>x64</Platform>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\2\2\2.proj"" />
<ProjectReference Include=""$(MSBuildThisFileDirectory)\..\..\3\3\3.proj"" />
</ItemGroup>
</Project>
");
TransientTestFolder project2Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, secondProjectName), createFolder: true);
TransientTestFolder project2SubFolder = testEnvironment.CreateFolder(Path.Combine(project2Folder.Path, secondProjectName), createFolder: true);
TransientTestFile project2 = testEnvironment.CreateFile(project2SubFolder, $"{secondProjectName}.proj",
@"<Project>
<PropertyGroup>
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
</Project>
");
TransientTestFolder project3Folder = testEnvironment.CreateFolder(Path.Combine(folder.Path, thirdProjectName), createFolder: true);
TransientTestFolder project3SubFolder = testEnvironment.CreateFolder(Path.Combine(project3Folder.Path, thirdProjectName), createFolder: true);
TransientTestFile project3 = testEnvironment.CreateFile(project3SubFolder, $"{thirdProjectName}.proj",
@"<Project>
<PropertyGroup>
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
</Project>
");
// Slashes here (and in the .slnf) are hardcoded as backslashes intentionally to support the common case.
TransientTestFile solutionFile = testEnvironment.CreateFile(folder, "SimpleProject.sln",
@"
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29326.124
MinimumVisualStudioVersion = 10.0.40219.1
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""Project1"", ""1\1\1.csproj"", ""{79B5EBA6-5D27-4976-BC31-14422245A59A}""
EndProject
Project(""{9A19103F-16F7-4668-BE54-9A1E7A4F7556}"") = ""2"", ""2\2\2.proj"", ""{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}""
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.ActiveCfg = Debug|x64
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Debug|x64.Build.0 = Debug|x64
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.ActiveCfg = Release|x64
{79B5EBA6-5D27-4976-BC31-14422245A59A}.Release|x64.Build.0 = Release|x64
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.ActiveCfg = Debug|Any CPU
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Debug|x64.Build.0 = Debug|Any CPU
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.ActiveCfg = Release|Any CPU
{8EFCCA22-9D51-4268-90F7-A595E11FCB2D}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DE7234EC-0C4D-4070-B66A-DCF1B4F0CFEF}
EndGlobalSection
EndGlobal
");
ProjectCollection projectCollection = testEnvironment.CreateProjectCollection().Collection;
MockLogger logger = new();
projectCollection.RegisterLogger(logger);
ProjectGraphEntryPoint entryPoint = new(solutionFile.Path, new Dictionary<string, string>());
// We want to make sure negotiation respects configuration if defined but negotiates if not.
ProjectGraph graphFromSolution = new(entryPoint, projectCollection);
logger.AssertNoErrors();
GetFirstNodeWithProjectNumber(graphFromSolution, 2).ProjectInstance.GetPropertyValue("Platform").ShouldBe("AnyCPU", "Project2 should have followed the sln config to AnyCPU");
GetFirstNodeWithProjectNumber(graphFromSolution, 3).ProjectInstance.GetPropertyValue("Platform").ShouldBe("x64", "Project3 isn't in the solution so it should have negotiated to x64 to match Project1");
}
}
}
}

Просмотреть файл

@ -3,9 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -60,7 +58,7 @@ namespace Microsoft.Build.Construction
/// Get the When children.
/// Will contain at least one entry.
/// </summary>
public ICollection<ProjectWhenElement> WhenElements => new ReadOnlyCollection<ProjectWhenElement>(Children.OfType<ProjectWhenElement>());
public ICollection<ProjectWhenElement> WhenElements => GetChildrenOfType<ProjectWhenElement>();
/// <summary>
/// Get any Otherwise child.

Просмотреть файл

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -59,10 +60,15 @@ namespace Microsoft.Build.Construction
}
/// <summary>
/// Get an enumerator over all children, gotten recursively.
/// Walks the children in a depth-first manner.
/// Get an enumerator over all descendants in a depth-first manner.
/// </summary>
public IEnumerable<ProjectElement> AllChildren => GetChildrenRecursively();
public IEnumerable<ProjectElement> AllChildren => GetDescendants();
internal IEnumerable<T> GetAllChildrenOfType<T>()
where T : ProjectElement
=> FirstChild == null
? Array.Empty<T>()
: GetDescendantsOfType<T>();
/// <summary>
/// Get enumerable over all the children
@ -70,26 +76,41 @@ namespace Microsoft.Build.Construction
public ICollection<ProjectElement> Children
{
[DebuggerStepThrough]
get
{
return new Collections.ReadOnlyCollection<ProjectElement>(
new ProjectElementSiblingEnumerable(FirstChild));
}
get => FirstChild == null
? Array.Empty<ProjectElement>()
: new Collections.ReadOnlyCollection<ProjectElement>(new ProjectElementSiblingEnumerable(FirstChild));
}
#pragma warning disable RS0030 // The ref to the banned API is in a doc comment
/// <summary>
/// Use this instead of <see cref="Children"/> to avoid boxing.
/// </summary>
#pragma warning restore RS0030
internal ProjectElementSiblingEnumerable ChildrenEnumerable => new ProjectElementSiblingEnumerable(FirstChild);
internal ProjectElementSiblingSubTypeCollection<T> GetChildrenOfType<T>()
where T : ProjectElement
=> FirstChild == null
? ProjectElementSiblingSubTypeCollection<T>.Empty
: new ProjectElementSiblingSubTypeCollection<T>(FirstChild);
/// <summary>
/// Get enumerable over all the children, starting from the last
/// </summary>
public ICollection<ProjectElement> ChildrenReversed
{
[DebuggerStepThrough]
get
{
return new Collections.ReadOnlyCollection<ProjectElement>(
new ProjectElementSiblingEnumerable(LastChild, false /* reverse */));
}
get => LastChild == null
? Array.Empty<ProjectElement>()
: new Collections.ReadOnlyCollection<ProjectElement>(new ProjectElementSiblingEnumerable(LastChild, forwards: false));
}
internal ProjectElementSiblingSubTypeCollection<T> GetChildrenReversedOfType<T>()
where T : ProjectElement
=> LastChild == null
? ProjectElementSiblingSubTypeCollection<T>.Empty
: new ProjectElementSiblingSubTypeCollection<T>(LastChild, forwards: false);
/// <summary>
/// Number of children of any kind
/// </summary>
@ -318,7 +339,7 @@ namespace Microsoft.Build.Construction
/// </remarks>
public void RemoveAllChildren()
{
foreach (ProjectElement child in Children)
foreach (ProjectElement child in ChildrenEnumerable)
{
RemoveChild(child);
}
@ -341,7 +362,7 @@ namespace Microsoft.Build.Construction
RemoveAllChildren();
CopyFrom(element);
foreach (ProjectElement child in element.Children)
foreach (ProjectElement child in element.ChildrenEnumerable)
{
if (child is ProjectElementContainer childContainer)
{
@ -395,7 +416,7 @@ namespace Microsoft.Build.Construction
var clone = (ProjectElementContainer)Clone(factory);
parent?.AppendChild(clone);
foreach (ProjectElement child in Children)
foreach (ProjectElement child in ChildrenEnumerable)
{
if (child is ProjectElementContainer childContainer)
{
@ -667,7 +688,7 @@ namespace Microsoft.Build.Construction
/// Result does NOT include the element passed in.
/// The caller could filter these.
/// </summary>
private IEnumerable<ProjectElement> GetChildrenRecursively()
private IEnumerable<ProjectElement> GetDescendants()
{
ProjectElement child = FirstChild;
@ -687,6 +708,30 @@ namespace Microsoft.Build.Construction
}
}
private IEnumerable<T> GetDescendantsOfType<T>()
where T : ProjectElement
{
ProjectElement child = FirstChild;
while (child != null)
{
if (child is T childOfType)
{
yield return childOfType;
}
if (child is ProjectElementContainer container)
{
foreach (T grandchild in container.GetAllChildrenOfType<T>())
{
yield return grandchild;
}
}
child = child.NextSibling;
}
}
private static bool TrySearchLeftSiblings(ProjectElement initialElement, Predicate<ProjectElement> siblingIsAcceptable, out ProjectElement referenceSibling)
{
return TrySearchSiblings(initialElement, siblingIsAcceptable, s => s.PreviousSibling, out referenceSibling);
@ -721,44 +766,182 @@ namespace Microsoft.Build.Construction
return referenceSibling != null;
}
internal sealed class ProjectElementSiblingSubTypeCollection<T> : ICollection<T>, ICollection
where T : ProjectElement
{
private readonly ProjectElement _initial;
private readonly bool _forwards;
private List<T> _realizedElements;
internal ProjectElementSiblingSubTypeCollection(ProjectElement initial, bool forwards = true)
{
_initial = initial;
_forwards = forwards;
}
public static ProjectElementSiblingSubTypeCollection<T> Empty { get; } = new ProjectElementSiblingSubTypeCollection<T>(initial: null);
public int Count => RealizedElements.Count;
public bool IsReadOnly => true;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => this;
private List<T> RealizedElements
{
get
{
if (_realizedElements == null)
{
// Note! Don't use the List ctor which takes an IEnumerable as it casts to an ICollection and calls Count,
// which leads to a StackOverflow exception in this implementation (see Count above)
List<T> list = new();
foreach (T element in this)
{
list.Add(element);
}
_realizedElements = list;
}
return _realizedElements;
}
}
public void Add(T item) => ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
public void Clear() => ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
public bool Contains(T item) => RealizedElements.Contains(item);
public void CopyTo(T[] array, int arrayIndex)
{
ErrorUtilities.VerifyThrowArgumentNull(array, nameof(array));
if (_realizedElements != null)
{
_realizedElements.CopyTo(array, arrayIndex);
}
else
{
int i = arrayIndex;
foreach (T entry in this)
{
array[i] = entry;
i++;
}
}
}
public bool Remove(T item)
{
ErrorUtilities.ThrowInvalidOperation("OM_NotSupportedReadOnlyCollection");
return false;
}
public IEnumerator<T> GetEnumerator() => new Enumerator(_initial, _forwards);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
void ICollection.CopyTo(Array array, int index)
{
ErrorUtilities.VerifyThrowArgumentNull(array, nameof(array));
int i = index;
foreach (T entry in this)
{
array.SetValue(entry, i);
i++;
}
}
public struct Enumerator : IEnumerator<T>
{
// Note! Should not be readonly or we run into infinite loop issues with mutable structs
private ProjectElementSiblingEnumerable.Enumerator _innerEnumerator;
private T _current;
internal Enumerator(ProjectElement initial, bool forwards = true)
{
_innerEnumerator = new ProjectElementSiblingEnumerable.Enumerator(initial, forwards);
}
public T Current
{
get
{
if (_current != null)
{
return _current;
}
throw new InvalidOperationException();
}
}
object IEnumerator.Current => Current;
public readonly void Dispose()
{
}
public bool MoveNext()
{
while (_innerEnumerator.MoveNext())
{
ProjectElement innerCurrent = _innerEnumerator.Current;
if (innerCurrent is T innerCurrentOfType)
{
_current = innerCurrentOfType;
return true;
}
}
return false;
}
public void Reset()
{
_innerEnumerator.Reset();
_current = null;
}
}
}
/// <summary>
/// Enumerable over a series of sibling ProjectElement objects
/// </summary>
private struct ProjectElementSiblingEnumerable : IEnumerable<ProjectElement>
internal readonly struct ProjectElementSiblingEnumerable : IEnumerable<ProjectElement>
{
/// <summary>
/// The enumerator
/// </summary>
private readonly ProjectElementSiblingEnumerator _enumerator;
private readonly Enumerator _enumerator;
/// <summary>
/// Constructor allowing reverse enumeration
/// </summary>
internal ProjectElementSiblingEnumerable(ProjectElement initial, bool forwards = true)
{
_enumerator = new ProjectElementSiblingEnumerator(initial, forwards);
_enumerator = new Enumerator(initial, forwards);
}
/// <summary>
/// Get enumerator
/// </summary>
public readonly IEnumerator<ProjectElement> GetEnumerator()
{
return _enumerator;
}
public readonly IEnumerator<ProjectElement> GetEnumerator() => _enumerator;
/// <summary>
/// Get non generic enumerator
/// </summary>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _enumerator;
}
IEnumerator IEnumerable.GetEnumerator() => _enumerator;
/// <summary>
/// Enumerator over a series of sibling ProjectElement objects
/// </summary>
private struct ProjectElementSiblingEnumerator : IEnumerator<ProjectElement>
public struct Enumerator : IEnumerator<ProjectElement>
{
/// <summary>
/// First element
@ -775,7 +958,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Constructor taking the first element
/// </summary>
internal ProjectElementSiblingEnumerator(ProjectElement initial, bool forwards)
internal Enumerator(ProjectElement initial, bool forwards)
{
_initial = initial;
Current = null;
@ -792,7 +975,7 @@ namespace Microsoft.Build.Construction
/// Current element.
/// Throws if MoveNext() hasn't been called
/// </summary>
object System.Collections.IEnumerator.Current
object IEnumerator.Current
{
get
{

Просмотреть файл

@ -3,8 +3,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -51,7 +49,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get any contained properties.
/// </summary>
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(Children.OfType<ProjectImportElement>());
public ICollection<ProjectImportElement> Imports => GetChildrenOfType<ProjectImportElement>();
#endregion // Properties

Просмотреть файл

@ -3,9 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -52,7 +50,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get any child metadata definitions.
/// </summary>
public ICollection<ProjectMetadataElement> Metadata => new ReadOnlyCollection<ProjectMetadataElement>(Children.OfType<ProjectMetadataElement>());
public ICollection<ProjectMetadataElement> Metadata => GetChildrenOfType<ProjectMetadataElement>();
/// <summary>
/// Convenience method to add a piece of metadata to this item definition.

Просмотреть файл

@ -3,9 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -47,7 +45,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get a list of child item definitions.
/// </summary>
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(Children.OfType<ProjectItemDefinitionElement>());
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => GetChildrenOfType<ProjectItemDefinitionElement>();
/// <summary>
/// Convenience method that picks a location based on a heuristic:

Просмотреть файл

@ -4,9 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -285,7 +283,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get any child metadata.
/// </summary>
public ICollection<ProjectMetadataElement> Metadata => new ReadOnlyCollection<ProjectMetadataElement>(Children.OfType<ProjectMetadataElement>());
public ICollection<ProjectMetadataElement> Metadata => GetChildrenOfType<ProjectMetadataElement>();
/// <summary>
/// Location of the include attribute

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -55,7 +54,7 @@ namespace Microsoft.Build.Construction
/// Get any child items.
/// This is a live collection.
/// </summary>
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(Children.OfType<ProjectItemElement>());
public ICollection<ProjectItemElement> Items => GetChildrenOfType<ProjectItemElement>();
/// <summary>
/// True if it is known that no child items have wildcards in their

Просмотреть файл

@ -3,8 +3,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -57,17 +55,17 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get an enumerator over any child item groups
/// </summary>
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
/// <summary>
/// Get an enumerator over any child property groups
/// </summary>
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
/// <summary>
/// Get an enumerator over any child chooses
/// </summary>
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
#endregion

Просмотреть файл

@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -47,12 +45,12 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get any contained properties.
/// </summary>
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(Children.OfType<ProjectPropertyElement>());
public ICollection<ProjectPropertyElement> Properties => GetChildrenOfType<ProjectPropertyElement>();
/// <summary>
/// Get any contained properties.
/// </summary>
public ICollection<ProjectPropertyElement> PropertiesReversed => new ReadOnlyCollection<ProjectPropertyElement>(ChildrenReversed.OfType<ProjectPropertyElement>());
public ICollection<ProjectPropertyElement> PropertiesReversed => GetChildrenReversedOfType<ProjectPropertyElement>();
/// <summary>
/// Convenience method that picks a location based on a heuristic:

Просмотреть файл

@ -287,81 +287,81 @@ namespace Microsoft.Build.Construction
/// <remarks>
/// The name is inconsistent to make it more understandable, per API review.
/// </remarks>
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
/// <summary>
/// Get a read-only collection of the child item definition groups, if any
/// </summary>
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroups => new ReadOnlyCollection<ProjectItemDefinitionGroupElement>(Children.OfType<ProjectItemDefinitionGroupElement>());
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroups => GetChildrenOfType<ProjectItemDefinitionGroupElement>();
/// <summary>
/// Get a read-only collection of the child item definitions, if any, in all item definition groups anywhere in the project file.
/// </summary>
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(AllChildren.OfType<ProjectItemDefinitionElement>());
public ICollection<ProjectItemDefinitionElement> ItemDefinitions => new ReadOnlyCollection<ProjectItemDefinitionElement>(GetAllChildrenOfType<ProjectItemDefinitionElement>());
/// <summary>
/// Get a read-only collection over the child item groups, if any.
/// Does not include any that may not be at the root, i.e. inside Choose elements.
/// </summary>
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
/// <summary>
/// Get a read-only collection of the child items, if any, in all item groups anywhere in the project file.
/// Not restricted to root item groups: traverses through Choose elements.
/// </summary>
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(AllChildren.OfType<ProjectItemElement>());
public ICollection<ProjectItemElement> Items => new ReadOnlyCollection<ProjectItemElement>(GetAllChildrenOfType<ProjectItemElement>());
/// <summary>
/// Get a read-only collection of the child import groups, if any.
/// </summary>
public ICollection<ProjectImportGroupElement> ImportGroups => new ReadOnlyCollection<ProjectImportGroupElement>(Children.OfType<ProjectImportGroupElement>());
public ICollection<ProjectImportGroupElement> ImportGroups => GetChildrenOfType<ProjectImportGroupElement>();
/// <summary>
/// Get a read-only collection of the child imports
/// </summary>
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(AllChildren.OfType<ProjectImportElement>());
public ICollection<ProjectImportElement> Imports => new ReadOnlyCollection<ProjectImportElement>(GetAllChildrenOfType<ProjectImportElement>());
/// <summary>
/// Get a read-only collection of the child property groups, if any.
/// Does not include any that may not be at the root, i.e. inside Choose elements.
/// </summary>
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
/// <summary>
/// Geta read-only collection of the child properties, if any, in all property groups anywhere in the project file.
/// Not restricted to root property groups: traverses through Choose elements.
/// </summary>
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(AllChildren.OfType<ProjectPropertyElement>());
public ICollection<ProjectPropertyElement> Properties => new ReadOnlyCollection<ProjectPropertyElement>(GetAllChildrenOfType<ProjectPropertyElement>());
/// <summary>
/// Get a read-only collection of the child targets
/// </summary>
public ICollection<ProjectTargetElement> Targets => new ReadOnlyCollection<ProjectTargetElement>(Children.OfType<ProjectTargetElement>());
public ICollection<ProjectTargetElement> Targets => GetChildrenOfType<ProjectTargetElement>();
/// <summary>
/// Get a read-only collection of the child usingtasks, if any
/// </summary>
public ICollection<ProjectUsingTaskElement> UsingTasks => new ReadOnlyCollection<ProjectUsingTaskElement>(Children.OfType<ProjectUsingTaskElement>());
public ICollection<ProjectUsingTaskElement> UsingTasks => GetChildrenOfType<ProjectUsingTaskElement>();
/// <summary>
/// Get a read-only collection of the child item groups, if any, in reverse order
/// </summary>
public ICollection<ProjectItemGroupElement> ItemGroupsReversed => new ReadOnlyCollection<ProjectItemGroupElement>(ChildrenReversed.OfType<ProjectItemGroupElement>());
public ICollection<ProjectItemGroupElement> ItemGroupsReversed => GetChildrenReversedOfType<ProjectItemGroupElement>();
/// <summary>
/// Get a read-only collection of the child item definition groups, if any, in reverse order
/// </summary>
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroupsReversed => new ReadOnlyCollection<ProjectItemDefinitionGroupElement>(ChildrenReversed.OfType<ProjectItemDefinitionGroupElement>());
public ICollection<ProjectItemDefinitionGroupElement> ItemDefinitionGroupsReversed => GetChildrenReversedOfType<ProjectItemDefinitionGroupElement>();
/// <summary>
/// Get a read-only collection of the child import groups, if any, in reverse order
/// </summary>
public ICollection<ProjectImportGroupElement> ImportGroupsReversed => new ReadOnlyCollection<ProjectImportGroupElement>(ChildrenReversed.OfType<ProjectImportGroupElement>());
public ICollection<ProjectImportGroupElement> ImportGroupsReversed => GetChildrenReversedOfType<ProjectImportGroupElement>();
/// <summary>
/// Get a read-only collection of the child property groups, if any, in reverse order
/// </summary>
public ICollection<ProjectPropertyGroupElement> PropertyGroupsReversed => new ReadOnlyCollection<ProjectPropertyGroupElement>(ChildrenReversed.OfType<ProjectPropertyGroupElement>());
public ICollection<ProjectPropertyGroupElement> PropertyGroupsReversed => GetChildrenReversedOfType<ProjectPropertyGroupElement>();
#endregion
@ -702,7 +702,7 @@ namespace Microsoft.Build.Construction
/// Not public as we do not wish to encourage the use of ProjectExtensions.
/// </remarks>
internal ProjectExtensionsElement ProjectExtensions
=> ChildrenReversed.OfType<ProjectExtensionsElement>().FirstOrDefault();
=> GetChildrenReversedOfType<ProjectExtensionsElement>().FirstOrDefault();
/// <summary>
/// Returns an unlocalized indication of how this file was last dirtied.
@ -1905,15 +1905,18 @@ namespace Microsoft.Build.Construction
}
}
foreach (var sdkNode in Children.OfType<ProjectSdkElement>())
foreach (ProjectElement child in ChildrenEnumerable)
{
var referencedSdk = new SdkReference(
sdkNode.XmlElement.GetAttribute("Name"),
sdkNode.XmlElement.GetAttribute("Version"),
sdkNode.XmlElement.GetAttribute("MinimumVersion"));
if (child is ProjectSdkElement sdkNode)
{
var referencedSdk = new SdkReference(
sdkNode.XmlElement.GetAttribute("Name"),
sdkNode.XmlElement.GetAttribute("Version"),
sdkNode.XmlElement.GetAttribute("MinimumVersion"));
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.props", currentProjectOrImport, ImplicitImportLocation.Top, referencedSdk, sdkNode));
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.targets", currentProjectOrImport, ImplicitImportLocation.Bottom, referencedSdk, sdkNode));
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.props", currentProjectOrImport, ImplicitImportLocation.Top, referencedSdk, sdkNode));
nodes.Add(ProjectImportElement.CreateImplicit("Sdk.targets", currentProjectOrImport, ImplicitImportLocation.Bottom, referencedSdk, sdkNode));
}
}
return nodes;

Просмотреть файл

@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.Execution;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -58,22 +56,22 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get an enumerator over any child item groups
/// </summary>
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
/// <summary>
/// Get an enumerator over any child property groups
/// </summary>
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
/// <summary>
/// Get an enumerator over any child tasks
/// </summary>
public ICollection<ProjectTaskElement> Tasks => new ReadOnlyCollection<ProjectTaskElement>(Children.OfType<ProjectTaskElement>());
public ICollection<ProjectTaskElement> Tasks => GetChildrenOfType<ProjectTaskElement>();
/// <summary>
/// Get an enumerator over any child onerrors
/// </summary>
public ICollection<ProjectOnErrorElement> OnErrors => new ReadOnlyCollection<ProjectOnErrorElement>(Children.OfType<ProjectOnErrorElement>());
public ICollection<ProjectOnErrorElement> OnErrors => GetChildrenOfType<ProjectOnErrorElement>();
#endregion

Просмотреть файл

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
@ -126,7 +125,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Gets any output children.
/// </summary>
public ICollection<ProjectOutputElement> Outputs => new Collections.ReadOnlyCollection<ProjectOutputElement>(Children.OfType<ProjectOutputElement>());
public ICollection<ProjectOutputElement> Outputs => GetChildrenOfType<ProjectOutputElement>();
/// <summary>
/// Enumerable over the unevaluated parameters on the task.

Просмотреть файл

@ -3,9 +3,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
@ -48,17 +46,17 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get an enumerator over any child chooses
/// </summary>
public ICollection<ProjectChooseElement> ChooseElements => new ReadOnlyCollection<ProjectChooseElement>(Children.OfType<ProjectChooseElement>());
public ICollection<ProjectChooseElement> ChooseElements => GetChildrenOfType<ProjectChooseElement>();
/// <summary>
/// Get an enumerator over any child item groups
/// </summary>
public ICollection<ProjectItemGroupElement> ItemGroups => new ReadOnlyCollection<ProjectItemGroupElement>(Children.OfType<ProjectItemGroupElement>());
public ICollection<ProjectItemGroupElement> ItemGroups => GetChildrenOfType<ProjectItemGroupElement>();
/// <summary>
/// Get an enumerator over any child property groups
/// </summary>
public ICollection<ProjectPropertyGroupElement> PropertyGroups => new ReadOnlyCollection<ProjectPropertyGroupElement>(Children.OfType<ProjectPropertyGroupElement>());
public ICollection<ProjectPropertyGroupElement> PropertyGroups => GetChildrenOfType<ProjectPropertyGroupElement>();
#endregion

Просмотреть файл

@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.Build.Collections;
using Microsoft.Build.ObjectModelRemoting;
using Microsoft.Build.Shared;
using ProjectXmlUtilities = Microsoft.Build.Internal.ProjectXmlUtilities;
@ -59,7 +57,7 @@ namespace Microsoft.Build.Construction
/// <summary>
/// Get any contained parameters.
/// </summary>
public ICollection<ProjectUsingTaskParameterElement> Parameters => new ReadOnlyCollection<ProjectUsingTaskParameterElement>(Children.OfType<ProjectUsingTaskParameterElement>());
public ICollection<ProjectUsingTaskParameterElement> Parameters => GetChildrenOfType<ProjectUsingTaskParameterElement>();
/// <summary>
/// This does not allow conditions, so it should not be called.

Просмотреть файл

@ -1062,7 +1062,7 @@ namespace Microsoft.Build.Evaluation
preserveFormatting: false);
}
foreach (ProjectElement elementXml in projectRootElement.Children)
foreach (ProjectElement elementXml in projectRootElement.ChildrenEnumerable)
{
ProjectUsingTaskElement usingTask = elementXml as ProjectUsingTaskElement;

Просмотреть файл

@ -535,7 +535,7 @@ namespace Microsoft.Build.Evaluation
List<ProjectTargetInstanceChild> targetChildren = new List<ProjectTargetInstanceChild>(targetElement.Count);
List<ProjectOnErrorInstance> targetOnErrorChildren = new List<ProjectOnErrorInstance>();
foreach (ProjectElement targetChildElement in targetElement.Children)
foreach (ProjectElement targetChildElement in targetElement.ChildrenEnumerable)
{
using (evaluationProfiler.TrackElement(targetChildElement))
{
@ -881,7 +881,7 @@ namespace Microsoft.Build.Evaluation
}
}
foreach (ProjectElement element in currentProjectOrImport.Children)
foreach (ProjectElement element in currentProjectOrImport.ChildrenEnumerable)
{
switch (element)
{
@ -1499,7 +1499,7 @@ namespace Microsoft.Build.Evaluation
{
if (EvaluateConditionCollectingConditionedProperties(whenElement, ExpanderOptions.ExpandProperties, ParserOptions.AllowProperties))
{
EvaluateWhenOrOtherwiseChildren(whenElement.Children);
EvaluateWhenOrOtherwiseChildren(whenElement.ChildrenEnumerable);
return;
}
}
@ -1507,7 +1507,7 @@ namespace Microsoft.Build.Evaluation
// "Otherwise" elements never have a condition
if (chooseElement.OtherwiseElement != null)
{
EvaluateWhenOrOtherwiseChildren(chooseElement.OtherwiseElement.Children);
EvaluateWhenOrOtherwiseChildren(chooseElement.OtherwiseElement.ChildrenEnumerable);
}
}
}
@ -1517,7 +1517,7 @@ namespace Microsoft.Build.Evaluation
/// Returns true if the condition was true, so subsequent
/// WhenElements and Otherwise can be skipped.
/// </summary>
private bool EvaluateWhenOrOtherwiseChildren(IEnumerable<ProjectElement> children)
private bool EvaluateWhenOrOtherwiseChildren(ProjectElementContainer.ProjectElementSiblingEnumerable children)
{
foreach (ProjectElement element in children)
{

Просмотреть файл

@ -63,7 +63,7 @@ namespace Microsoft.Build.Graph
{
public TargetSpecification(string target, bool skipIfNonexistent)
{
// Verify that if this target is skippable then it equals neither
// Verify that if this target is skippable then it equals neither
// ".default" nor ".projectReferenceTargetsOrDefaultTargets".
ErrorUtilities.VerifyThrow(
!skipIfNonexistent || (!target.Equals(MSBuildConstants.DefaultTargetsMarker)
@ -131,6 +131,8 @@ namespace Microsoft.Build.Graph
allowCollectionReuse: solutionConfiguration == null && !enableDynamicPlatformResolution,
globalPropertiesModifiers);
bool configurationDefined = false;
// Match what AssignProjectConfiguration does to resolve project references.
if (solutionConfiguration != null)
{
@ -151,6 +153,8 @@ namespace Microsoft.Build.Graph
{
referenceGlobalProperties.Remove(PlatformMetadataName);
}
configurationDefined = true;
}
else
{
@ -161,11 +165,16 @@ namespace Microsoft.Build.Graph
referenceGlobalProperties.Remove(ConfigurationMetadataName);
referenceGlobalProperties.Remove(PlatformMetadataName);
}
else
{
configurationDefined = true;
}
}
}
// Note: Dynamic platform resolution is not enabled for sln-based builds.
else if (!projectReferenceItem.HasMetadata(SetPlatformMetadataName) && enableDynamicPlatformResolution)
// Note: Dynamic platform resolution is not enabled for sln-based builds,
// unless the project isn't known to the solution.
if (enableDynamicPlatformResolution && !configurationDefined && !projectReferenceItem.HasMetadata(SetPlatformMetadataName))
{
string requesterPlatform = requesterInstance.GetPropertyValue("Platform");
string requesterPlatformLookupTable = requesterInstance.GetPropertyValue("PlatformLookupTable");

Просмотреть файл

@ -6,6 +6,7 @@ using System.IO;
using System.IO.Compression;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
using Microsoft.Build.Shared.FileSystem;
#nullable disable
@ -226,12 +227,25 @@ namespace Microsoft.Build.Logging
if (projectImportsCollector != null)
{
projectImportsCollector.Close();
if (CollectProjectImports == ProjectImportsCollectionMode.Embed)
{
eventArgsWriter.WriteBlob(BinaryLogRecordKind.ProjectImportArchive, projectImportsCollector.GetAllBytes());
var archiveFilePath = projectImportsCollector.ArchiveFilePath;
// It is possible that the archive couldn't be created for some reason.
// Only embed it if it actually exists.
if (FileSystems.Default.FileExists(archiveFilePath))
{
using (FileStream fileStream = File.OpenRead(archiveFilePath))
{
eventArgsWriter.WriteBlob(BinaryLogRecordKind.ProjectImportArchive, fileStream);
}
File.Delete(archiveFilePath);
}
}
projectImportsCollector.Close();
projectImportsCollector = null;
}

Просмотреть файл

@ -218,6 +218,17 @@ namespace Microsoft.Build.Logging
Write(bytes);
}
public void WriteBlob(BinaryLogRecordKind kind, Stream stream)
{
// write the blob directly to the underlying writer,
// bypassing the memory stream
using var redirection = RedirectWritesToOriginalWriter();
Write(kind);
Write(stream.Length);
Write(stream);
}
/// <summary>
/// Switches the binaryWriter used by the Write* methods to the direct underlying stream writer
/// until the disposable is disposed. Useful to bypass the currentRecordWriter to write a string,
@ -1091,6 +1102,11 @@ namespace Microsoft.Build.Logging
binaryWriter.Write(bytes);
}
private void Write(Stream stream)
{
stream.CopyTo(binaryWriter.BaseStream);
}
private void Write(byte b)
{
binaryWriter.Write(b);

Просмотреть файл

@ -7,6 +7,7 @@ using System.IO;
using System.IO.Compression;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Shared;
#nullable disable
@ -20,30 +21,10 @@ namespace Microsoft.Build.Logging
/// </summary>
internal class ProjectImportsCollector
{
private Stream _stream;
public byte[] GetAllBytes()
{
if (_stream == null)
{
return Array.Empty<byte>();
}
else if (ArchiveFilePath == null)
{
var stream = _stream as MemoryStream;
// Before we can use the zip archive, it must be closed.
Close(false);
return stream.ToArray();
}
else
{
Close();
return File.ReadAllBytes(ArchiveFilePath);
}
}
private Stream _fileStream;
private ZipArchive _zipArchive;
private string ArchiveFilePath { get; set; }
public string ArchiveFilePath { get; }
/// <summary>
/// Avoid visiting each file more than once.
@ -55,33 +36,46 @@ namespace Microsoft.Build.Logging
public ProjectImportsCollector(string logFilePath, bool createFile, string sourcesArchiveExtension = ".ProjectImports.zip")
{
if (createFile)
{
// Archive file will be stored alongside the binlog
ArchiveFilePath = Path.ChangeExtension(logFilePath, sourcesArchiveExtension);
}
else
{
string cacheDirectory = FileUtilities.GetCacheDirectory();
if (!Directory.Exists(cacheDirectory))
{
Directory.CreateDirectory(cacheDirectory);
}
// Archive file will be temporarily stored in MSBuild cache folder and deleted when no longer needed
ArchiveFilePath = Path.Combine(
cacheDirectory,
Path.ChangeExtension(
Path.GetFileName(logFilePath),
sourcesArchiveExtension));
}
try
{
if (createFile)
{
ArchiveFilePath = Path.ChangeExtension(logFilePath, sourcesArchiveExtension);
_stream = new FileStream(ArchiveFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
}
else
{
_stream = new MemoryStream();
}
_zipArchive = new ZipArchive(_stream, ZipArchiveMode.Create, true);
_fileStream = new FileStream(ArchiveFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
_zipArchive = new ZipArchive(_fileStream, ZipArchiveMode.Create);
}
catch
{
// For some reason we weren't able to create a file for the archive.
// Disable the file collector.
_stream = null;
_fileStream = null;
_zipArchive = null;
}
}
public void AddFile(string filePath)
{
if (filePath != null && _stream != null)
if (filePath != null && _fileStream != null)
{
lock (_stream)
lock (_fileStream)
{
// enqueue the task to add a file and return quickly
// to avoid holding up the current thread
@ -101,9 +95,9 @@ namespace Microsoft.Build.Logging
public void AddFileFromMemory(string filePath, string data)
{
if (filePath != null && data != null && _stream != null)
if (filePath != null && data != null && _fileStream != null)
{
lock (_stream)
lock (_fileStream)
{
// enqueue the task to add a file and return quickly
// to avoid holding up the current thread
@ -197,7 +191,7 @@ namespace Microsoft.Build.Logging
return archivePath;
}
public void Close(bool closeStream = true)
public void Close()
{
// wait for all pending file writes to complete
_currentTask.Wait();
@ -208,10 +202,10 @@ namespace Microsoft.Build.Logging
_zipArchive = null;
}
if (closeStream && (_stream != null))
if (_fileStream != null)
{
_stream.Dispose();
_stream = null;
_fileStream.Dispose();
_fileStream = null;
}
}
}

Просмотреть файл

@ -79,7 +79,7 @@
<PackageReference Update="Microsoft.NETCore.App" PrivateAssets="All" />
<!-- Configure analyzer to forbid certain API calls -->
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" Condition=" '$(IsUnitTestProject)' != 'true' " />
</ItemGroup>
<PropertyGroup Condition="'$(GenerateReferenceAssemblySource)' == 'true'">

Просмотреть файл

@ -1498,8 +1498,8 @@ namespace Microsoft.Build.CommandLine
}
finally
{
FileUtilities.ClearCacheDirectory();
projectCollection?.Dispose();
FileUtilities.ClearCacheDirectory();
// Build manager shall be reused for all build sessions.
// If, for one reason or another, this behavior needs to change in future

Просмотреть файл

@ -20,7 +20,7 @@ namespace Microsoft.Build.Collections
/// Thus this is an omission from the BCL.
/// </remarks>
/// <typeparam name="T">Type of element in the collection</typeparam>
internal class ReadOnlyCollection<T> : ICollection<T>, ICollection
internal sealed class ReadOnlyCollection<T> : ICollection<T>, ICollection
{
/// <summary>
/// Backing live enumerable.

Просмотреть файл

@ -1648,7 +1648,6 @@ Copyright (C) Microsoft Corporation. All rights reserved.
Configuration information. See AssignProjectConfiguration -->
<Target Name="_GetProjectReferencePlatformProperties"
Condition="'$(EnableDynamicPlatformResolution)' == 'true'
and '$(CurrentSolutionConfigurationContents)' == ''
and '@(_MSBuildProjectReferenceExistent)' != ''">
<!-- Allow preset SetPlatform to override this operation -->